|
| 1 | +# Klaviyo React Native SDK Example App |
| 2 | + |
| 3 | +The example app is a reference integration of the Klaviyo React Native SDK. It |
| 4 | +demonstrates where and how to `initialize`, implement notification delegate |
| 5 | +methods on iOS, handle opened notification intents on Android, and exercise the |
| 6 | +SDK's public API surface (profile, events, in-app forms, geofencing, push). |
| 7 | +Sample code is annotated — search for `JS Installation Step`, `iOS Installation Step`, |
| 8 | +and `Android Installation Step` in the source to find the integration callouts. |
| 9 | + |
| 10 | +## Getting Started |
| 11 | + |
| 12 | +### 1. Configure Your API Key |
| 13 | + |
| 14 | +The app loads your Klaviyo public API key from a gitignored `.env` file via |
| 15 | +[`react-native-dotenv`](https://github.com/goatandsheep/react-native-dotenv). |
| 16 | + |
| 17 | +1. Copy the template: `cp .env.template .env` |
| 18 | +2. Edit `.env` and set `KLAVIYO_API_KEY=` to your actual public API key |
| 19 | +3. Restart Metro with `yarn start --reset-cache` so the babel plugin picks up the new value |
| 20 | + |
| 21 | +> **If you hit "Klaviyo API key not configured" after setting up `.env`:** Metro inlines |
| 22 | +> `.env` values at bundle time via `react-native-dotenv`. If Metro was already running when |
| 23 | +> you created or edited `.env`, it will serve a cached bundle with `KLAVIYO_API_KEY` still |
| 24 | +> undefined. Stop Metro and restart it with `yarn start --reset-cache` (from `example/`). |
| 25 | +
|
| 26 | +Notes: |
| 27 | + |
| 28 | +- `.env` is gitignored — only `.env.template` is checked in. |
| 29 | +- If `KLAVIYO_API_KEY` is missing or still set to the placeholder, the app fails |
| 30 | + fast at module load with a clear error — no silent misbehavior. Copy |
| 31 | + `.env.template` to `.env` and set a real key before running. |
| 32 | + |
| 33 | +### 2. Install Dependencies |
| 34 | + |
| 35 | +The one-liner, run from the repo root: |
| 36 | + |
| 37 | +```bash |
| 38 | +# From the repo root |
| 39 | +yarn example setup |
| 40 | + |
| 41 | +# This alias runs: |
| 42 | +# yarn install --immutable (repo root) |
| 43 | +# bundle install (example/) |
| 44 | +# bundle exec pod install (example/ios/) |
| 45 | +``` |
| 46 | + |
| 47 | +You can run those steps manually if you prefer, but `yarn example setup` is the |
| 48 | +preferred entry point. |
| 49 | + |
| 50 | +### 3. Run the App |
| 51 | + |
| 52 | +Preferred — from the repo root (yarn workspaces entry point): |
| 53 | + |
| 54 | +```bash |
| 55 | +# From the repo root |
| 56 | +yarn example start |
| 57 | +yarn example android |
| 58 | +yarn example ios |
| 59 | +``` |
| 60 | + |
| 61 | +Alternatively, from the `example/` directory: |
| 62 | + |
| 63 | +```bash |
| 64 | +# Start Metro bundler |
| 65 | +yarn start |
| 66 | + |
| 67 | +# Run iOS |
| 68 | +yarn ios |
| 69 | + |
| 70 | +# Run Android |
| 71 | +yarn android |
| 72 | +``` |
| 73 | + |
| 74 | +## Push Notifications |
| 75 | + |
| 76 | +**Push is disabled by default.** The example app launches without any Firebase |
| 77 | +configuration — the rest of the demo (profile management, events, in-app forms, |
| 78 | +geofencing) still works, and the Push Notifications section just shows setup |
| 79 | +instructions until you wire Firebase up. |
| 80 | + |
| 81 | +Push notifications are handled via `@react-native-firebase/messaging` in the |
| 82 | +JavaScript layer. This is the recommended approach for React Native apps — the |
| 83 | +SDK is initialized from JS, and Firebase manages push tokens cross-platform. |
| 84 | + |
| 85 | +### Firebase Setup |
| 86 | + |
| 87 | +To enable push notifications, add your Firebase configuration files: |
| 88 | + |
| 89 | +**iOS:** |
| 90 | + |
| 91 | +1. Add `GoogleService-Info.plist` to `example/ios/KlaviyoReactNativeSdkExample/` |
| 92 | +2. Run `pod install` from the `example/ios/` directory |
| 93 | + |
| 94 | +**Android:** |
| 95 | + |
| 96 | +1. Replace `example/android/app/google-services.json.template` with a real |
| 97 | + `google-services.json` from your Firebase project. |
| 98 | + - The template is a placeholder structure checked into the repo so that the |
| 99 | + Android build succeeds without real Firebase config. It lets the app run |
| 100 | + (with push simply disabled) on a cold clone. Replace it with a real |
| 101 | + `google-services.json` to enable push on Android. |
| 102 | + - `google-services.json` itself is gitignored — only the template is checked in. |
| 103 | +2. Ensure `applicationId` in `build.gradle` matches your Firebase project. |
| 104 | + |
| 105 | +The app automatically detects Firebase and enables push features once the config |
| 106 | +files are in place. |
| 107 | + |
| 108 | +### Native Push (Alternative) |
| 109 | + |
| 110 | +For apps that prefer to handle push tokens natively (e.g., brownfield apps), the native code in `AppDelegate.mm` and `MainApplication.kt` contains commented-out reference implementations. See those files for details. |
| 111 | + |
| 112 | +Note: `Klaviyo.handlePush(intent)` in `MainActivity.kt` is always required on Android — push open tracking depends on native intent handling regardless of how tokens are managed. |
| 113 | + |
| 114 | +## Integration Step Comments |
| 115 | + |
| 116 | +The example source is annotated with `JS Installation Step`, `iOS Installation Step`, |
| 117 | +and `Android Installation Step` comments that mark the code an integrator needs to |
| 118 | +replicate in their own app. Grep for any of those prefixes across `example/` to walk |
| 119 | +the integration surface: |
| 120 | + |
| 121 | +- `JS Installation Step` — `example/src/App.tsx` and `example/index.js` (SDK init, |
| 122 | + API key sourcing, optional `@react-native-firebase/messaging` background handler) |
| 123 | +- `iOS Installation Step` — `example/ios/KlaviyoReactNativeSdkExample/AppDelegate.{h,mm}`, |
| 124 | + `PushNotificationsHelper.swift`, `NotificationService.swift`, and the Podfile |
| 125 | +- `Android Installation Step` — `example/android/build.gradle`, `app/build.gradle`, |
| 126 | + `AndroidManifest.xml`, and `MainActivity.kt` |
| 127 | + |
| 128 | +Each comment is self-describing — the prefix is just a grep handle, not part of a |
| 129 | +strictly ordered checklist. Some steps are labelled by concern rather than being |
| 130 | +numbered (e.g., "Firebase, part 1 of 2") where that reads more clearly than an |
| 131 | +ordinal would. |
| 132 | + |
| 133 | +## Features Demonstrated |
| 134 | + |
| 135 | +- **Profile Management** — Set email, phone, external ID individually or together; reset profile |
| 136 | +- **Event Tracking** — Create test events and Viewed Product events |
| 137 | +- **In-App Forms** — Register/unregister with configurable session timeout |
| 138 | +- **Geofencing** — Location permission flow, register/unregister, list current geofences |
| 139 | +- **Push Notifications** — Firebase-based permission request, token display, badge count (iOS) |
| 140 | +- **Deep Linking** — Universal tracking link handling via `Linking` API |
0 commit comments