Skip to content

Commit 537311c

Browse files
committed
docs(example): update READMEs for JS-first init and Firebase push setup
Root README: rewrite the example-app section to reflect the JS-first initialization flow (API key via .env, Firebase push optional) instead of the removed initializeKlaviyoFromNative toggle. example/README.md: new standalone setup guide covering .env configuration, iOS Firebase setup (GoogleService-Info.plist + pod install), Android Firebase setup (google-services.json vs the shipped .template), and the push-disabled path (app runs cleanly without Firebase configured). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]> Manual readme review
1 parent cad277c commit 537311c

12 files changed

Lines changed: 203 additions & 75 deletions

File tree

README.md

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,29 +103,9 @@ yarn add klaviyo-react-native-sdk
103103

104104
### Example App
105105

106-
We have included an example app in this repository for reference of how to integrate with our SDK.
107-
It is primarily intended to give code samples such as how and where to `initialize`, implement notification
108-
delegate methods on iOS, and handle an opened notification intent on Android. We've commented the sample app
109-
code to call out key setup steps, search for `iOS Installation Step` and `Android Installation Step`.
110-
111-
To run the example app:
112-
113-
- Clone this repository
114-
- From the root directory, run `yarn example setup`. This is an alias that will do the following:
115-
- Run `yarn install --immutable` from the root directory
116-
- Navigate to the `example` directory and run `bundle install`
117-
- Navigate to the `example/ios` directory and run `bundle exec pod install`
118-
- Android configuration:
119-
- To initialize Klaviyo from the native layer, open `example/android/gradle.properties` and follow the
120-
instructions to set your `publicApiKey` and verify `initializeKlaviyoFromNative` is enabled.
121-
- If you wish to run the Android example app with push/firebase, you'll need to copy a `google-services.json`
122-
file into `example/android/app/src` and update the `applicationId` in `app/build.gradle` to match your application ID.
123-
Then, open `example/android/gradle.properties` and follow the instructions to enable `useNativeFirebase`.
124-
This is disabled by default because the app will crash on launch without a `google-services.json` file.
125-
- From the project's root directory, use the following commands start a metro server and run the example app.
126-
- `yarn example start` - to start the metro server
127-
- `yarn example android` - to run the example app on an Android emulator or device
128-
- `yarn example ios` - to run the example app on an iOS simulator
106+
The [example app](./example) is a reference integration demonstrating SDK setup and
107+
exercising the public API surface. See [`example/README.md`](./example/README.md) for
108+
setup instructions, Firebase configuration, and a walkthrough of the demonstrated features.
129109

130110
### Android
131111

example/README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Klaviyo React Native SDK Example App
2+
3+
The example app is a reference integration of the Klaviyo React Native SDK. It demonstrates
4+
a basic Klaviyo integration with all major SDK features including:
5+
6+
- Initialization
7+
- Analytics
8+
- Push Notifications
9+
- Geofencing
10+
- Deep Linking
11+
- In-App Forms
12+
13+
## Integration Step Comments
14+
15+
The example source is annotated with `RN|iOS|Android Installation Step` comments that mark
16+
the code an integrator needs to replicate in their own app. Grep for any of those prefixes
17+
across `example/` to walk the integration surface:
18+
19+
- `RN Installation Step``example/src/App.tsx` and `example/index.js` (SDK init,
20+
API key sourcing, optional `@react-native-firebase/messaging` background handler)
21+
- `iOS Installation Step``example/ios/KlaviyoReactNativeSdkExample/AppDelegate.{h,mm}`,
22+
`PushNotificationsHelper.swift`, `NotificationService.swift`, and the Podfile
23+
- `Android Installation Step``example/android/build.gradle`, `app/build.gradle`,
24+
`AndroidManifest.xml`, and `MainActivity.kt`
25+
26+
## Getting Started
27+
28+
### 1. Configure Your API Key
29+
30+
The app loads your Klaviyo public API key from a gitignored `.env` file via
31+
[`react-native-dotenv`](https://github.com/goatandsheep/react-native-dotenv).
32+
33+
1. Copy the template: `cp .env.template .env`
34+
2. Edit `.env` and set `KLAVIYO_API_KEY=` to your actual public API key (`.env` is gitignored)
35+
3. Restart Metro with `yarn start --reset-cache` so the metro picks up the new value
36+
37+
> **If you hit "Klaviyo API key not configured" after setting up `.env`:** Metro inlines
38+
> `.env` values at bundle time via `react-native-dotenv`. If Metro was already running when
39+
> you created or edited `.env`, it will serve a cached bundle with `KLAVIYO_API_KEY` still
40+
> undefined. Stop Metro and restart it with `yarn start --reset-cache` (from `example/`).
41+
42+
### 2. Install Dependencies
43+
44+
The one-liner, run from the repo root:
45+
46+
```bash
47+
# From the repo root
48+
yarn example setup
49+
50+
# This alias runs:
51+
# yarn install --immutable (repo root)
52+
# bundle install (example/)
53+
# bundle exec pod install (example/ios/)
54+
```
55+
56+
### 3. Run the App
57+
58+
Preferred — from the repo root (yarn workspaces entry point):
59+
60+
```bash
61+
# From the repo root
62+
yarn example start
63+
yarn example android
64+
yarn example ios
65+
```
66+
67+
## Push Notifications
68+
69+
Push notifications are handled via `@react-native-firebase/messaging` in the
70+
JavaScript layer — the Klaviyo SDK is initialized from JS, and Firebase manages
71+
push tokens cross-platform.
72+
73+
### Platform-specific Firebase setup
74+
75+
**Android** builds and runs out of the box without Firebase configured. The
76+
`com.google.gms.google-services` plugin is conditionally applied only when
77+
`google-services.json` is present. Without the file, push features are dormant
78+
but everything else (profile, events, in-app forms, geofencing) works normally.
79+
80+
- To enable push: drop a real `google-services.json` from your Firebase project
81+
into `example/android/app/`. The file is gitignored. Ensure the
82+
`applicationId` in `example/android/app/build.gradle`
83+
(`com.klaviyoreactnativesdkexample`) is registered as an Android app in your
84+
Firebase project.
85+
86+
**iOS** requires a `GoogleService-Info.plist` at `example/ios/` to build at all — the Xcode
87+
project's Resources build phase references it unconditionally. Two options:
88+
89+
- **To enable push:** drop a real `GoogleService-Info.plist` from your Firebase
90+
project at `example/ios/GoogleService-Info.plist` (gitignored). Ensure your
91+
iOS bundle identifier is registered in the same Firebase project.
92+
- **To build without push:** write a stub plist at the same path. The values
93+
below are format-valid (39-char `API_KEY` starting with `A`, full
94+
`GOOGLE_APP_ID` format), so `FirebaseApp.configure()` succeeds at launch.
95+
Firebase will log a benign "couldn't register with backend" warning at
96+
runtime since the project isn't real — that's expected, not a bug. The rest
97+
of the app works normally.
98+
<details>
99+
<summary>Stub <code>GoogleService-Info.plist</code></summary>
100+
101+
```xml
102+
<?xml version="1.0" encoding="UTF-8"?>
103+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
104+
<plist version="1.0">
105+
<dict>
106+
<key>BUNDLE_ID</key><string>com.klaviyoreactnativesdkexample</string>
107+
<key>GOOGLE_APP_ID</key><string>1:000000000000:ios:0000000000000000000000</string>
108+
<key>API_KEY</key><string>AIzaSyA00000000000000000000000000000000</string>
109+
<key>GCM_SENDER_ID</key><string>000000000000</string>
110+
<key>PROJECT_ID</key><string>stub-project</string>
111+
<key>STORAGE_BUCKET</key><string>stub-project.appspot.com</string>
112+
<key>PLIST_VERSION</key><string>1</string>
113+
<key>IS_GCM_ENABLED</key><true/>
114+
<key>IS_ADS_ENABLED</key><false/>
115+
<key>IS_ANALYTICS_ENABLED</key><false/>
116+
<key>IS_APPINVITE_ENABLED</key><false/>
117+
<key>IS_SIGNIN_ENABLED</key><false/>
118+
</dict>
119+
</plist>
120+
```
121+
122+
</details>
123+
124+
### Native push (alternative)
125+
126+
For apps that prefer to handle push tokens natively (e.g., brownfield apps), the
127+
Klaviyo iOS and Android SDKs both have their own native push APIs. See the
128+
`AppDelegate.mm` comments on iOS and `MainApplication.kt` comments on Android for
129+
pointers, plus the platform SDKs' READMEs:
130+
131+
- iOS: https://github.com/klaviyo/klaviyo-swift-sdk#push-notifications
132+
- Android: https://github.com/klaviyo/klaviyo-android-sdk#push-notifications
133+
134+
Note: both platforms require native-layer push-open handling regardless of how tokens
135+
are managed:
136+
137+
- **Android:** `Klaviyo.handlePush(intent)` in `MainActivity.kt` (`onCreate` +
138+
`onNewIntent`) — covers cold-start taps and resume-from-background taps.
139+
- **iOS:** `[PushNotificationsHelper handleReceivingPushWithResponse:...]` inside
140+
the `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:`
141+
delegate in `AppDelegate.mm`, plus the `getLaunchOptionsWithURL` helper to
142+
forward any cold-start deep-link URL (React Native issue
143+
[#32350](https://github.com/facebook/react-native/issues/32350)).

example/android/app/build.gradle

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ dependencies {
114114
// The version of react-native is set by the React Native Gradle Plugin
115115
implementation("com.facebook.react:react-android")
116116

117-
// Android Installation Step 1b - add firebase dependency if using push
117+
// Android Installation Step - add firebase dependency if using push
118118
implementation 'com.google.firebase:firebase-messaging-ktx:24.0.0'
119119

120120
if (hermesEnabled.toBoolean()) {
@@ -124,11 +124,14 @@ dependencies {
124124
}
125125
}
126126

127-
// Apply the google-services plugin only when google-services.json is present.
128-
// This lets the example app build out of the box without a Firebase project.
129-
// To enable push: drop your Firebase project's google-services.json into
130-
// example/android/app/, and make sure its package_name matches applicationId
131-
// above. See example/README.md for full setup details.
127+
// For the example app we only apply the google-services plugin
128+
// when google-services.json is present. This lets the example app build out of
129+
// the box without a Firebase project. To enable push: drop your Firebase
130+
// project's google-services.json into example/android/app/, and make sure its
131+
// package_name matches applicationId above. See example/README.md for full
132+
// setup details. The equivalent on iOS is the `#if __has_include(...)` +
133+
// `if (plistPath)` guard in example/ios/.../AppDelegate.mm.
132134
if (file('google-services.json').exists()) {
135+
// Optional Android Installation Step: Apply the google-services plugin to enable push
133136
apply plugin: "com.google.gms.google-services"
134137
}

example/android/app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<!-- Android Installation Step 2: Configure manifest.xml ... -->
21
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
32

43
<uses-permission android:name="android.permission.INTERNET" />
@@ -23,18 +22,18 @@
2322
<category android:name="android.intent.category.LAUNCHER" />
2423
</intent-filter>
2524

26-
<!-- Android Installation Step 2a: Configure deep links, if your push notifications will contain them -->
25+
<!-- Android Installation Step: Configure deep links, if your push notifications will contain them -->
2726
<intent-filter android:label="deep_link_filter">
2827
<action android:name="android.intent.action.VIEW"/>
2928

3029
<category android:name="android.intent.category.DEFAULT"/>
3130
<category android:name="android.intent.category.BROWSABLE"/>
3231

33-
<!-- Accepts URIs that begin with "klaviyosample://” -->
34-
<data android:scheme="klaviyosample"/>
32+
<!-- Accepts URIs that begin with "klaviyotest://” -->
33+
<data android:scheme="klaviyotest"/>
3534
</intent-filter>
3635

37-
<!-- Android Installation Step 2b: Configure verified app links for Universal Link Click Tracking -->
36+
<!-- Android Installation Step: Configure verified app links for Universal Link Click Tracking -->
3837
<intent-filter android:label="app_link_handler" android:autoVerify="true">
3938
<action android:name="android.intent.action.VIEW" />
4039
<category android:name="android.intent.category.DEFAULT" />
@@ -46,7 +45,7 @@
4645

4746
</activity>
4847

49-
<!-- Android Installation Step 2b: Register KlaviyoPushService to receive MESSAGING_EVENT intents. -->
48+
<!-- Android Installation Step: Register KlaviyoPushService to receive MESSAGING_EVENT intents. -->
5049
<service
5150
android:name="com.klaviyo.pushFcm.KlaviyoPushService"
5251
android:exported="false">
@@ -55,14 +54,14 @@
5554
</intent-filter>
5655
</service>
5756

58-
<!-- Optional Android Installation Step 2c: Specify an icon for Klaviyo notifications -->
57+
<!-- Optional Android Installation Step: Specify an icon for Klaviyo notifications -->
5958
<!-- Absent this key, Klaviyo SDK will look for com.google.firebase.messaging.default_notification_icon -->
6059
<!-- and absent that, use the default launcher icon for your app -->
6160
<meta-data
6261
android:name="com.klaviyo.push.default_notification_icon"
6362
android:resource="@drawable/ic_notification" />
6463

65-
<!-- Optional Android Installation Step 2d: Specify a notification color for Klaviyo notifications -->
64+
<!-- Optional Android Installation Step: Specify a notification color for Klaviyo notifications -->
6665
<!-- Absent this key, Klaviyo SDK will look for com.google.firebase.messaging.default_notification_color -->
6766
<!-- and absent that, omit specifying a color -->
6867
<meta-data android:name="com.klaviyo.push.default_notification_color"

example/android/app/src/main/java/com/klaviyoreactnativesdkexample/MainActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class MainActivity : ReactActivity() {
2727
Log.v("KlaviyoSampleApp", "MainActivity.onCreate()")
2828
super.onCreate(savedInstanceState)
2929

30-
// Android Installation Step 5a: Depending on the state of your application when the notification is tapped,
30+
// Android Installation Step: Depending on the state of your application when the notification is tapped,
3131
// the intent have started this activity, or it might be received via onNewIntent if the app was already running.
3232
// We recommend passing all intents through Klaviyo.handlePush to make sure you don't miss a use case.
3333
onNewIntent(intent)
@@ -38,7 +38,7 @@ class MainActivity : ReactActivity() {
3838
Log.v("KlaviyoSampleApp", "Launch Intent: " + intent.toString())
3939
super.onNewIntent(intent)
4040

41-
// Android Installation Step 5: Call handlePush when a push notification is tapped
41+
// Android Installation Step: Call handlePush when a push notification is tapped
4242
// Note: due to platform differences, this step must be implemented in native code.
4343
// Tapping on a notification broadcasts an intent to your app. This method detects if the
4444
// intent originated from a Klaviyo push notification and registers a special Opened Push event

example/android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
buildscript {
22
ext {
3-
// Android Installation Step 1a: Set compatible minSdkVersion and compileSdkVersion
43
minSdkVersion = 24
54
targetSdkVersion = 36 // Typically minSdkVersion <= targetSdkVersion <= compileSdkVersion
65
compileSdkVersion = 36
@@ -17,7 +16,8 @@ buildscript {
1716
classpath("com.facebook.react:react-native-gradle-plugin")
1817
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
1918

20-
// Android Installation Step - Required dependency to initialize firebase via google-services.json file
19+
// Android Installation Step: google-services Gradle plugin,
20+
// required to process google-services.json if you're enabling push.
2121
classpath("com.google.gms:google-services:4.4.2")
2222
}
2323
}

example/ios/KlaviyoReactNativeSdkExample/AppDelegate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#import "klaviyo_react_native_sdk-Swift.h"
99
#endif
1010

11-
// iOS Installation Step 1: Conform AppDelegate to UNUserNotificationCenterDelegate
1211
@interface AppDelegate: RCTAppDelegate <UNUserNotificationCenterDelegate>
1312

1413
@end

0 commit comments

Comments
 (0)