Open giorgiofellipe opened 1 month ago
Thanks for the feedback and the code you provided. We will take this as a feature request on our end. Unfortunately, we don't have a timeline on this but will keep this issue open and update it whenever we have something to share on this topic.
A heads up regarding my solution: it breaks the default deep link handling from Expo (when app is terminated). I appreciate if anyone from Klaviyo can jump in and help me make both work (Opened Push Event and Deep Link handling).
Hey giorgiofellipe, unfortunately we have set commitments to improve SDKs across the board that at this point we can't help with your request. However, as I mentioned earlier, we do have this as a feature request on our end and will update this thread as and when we have updates to share. Thanks!
Checklist
* [x] I have read the [contributing guidelines](https://github.com/klaviyo/klaviyo-react-native-sdk/blob/master/.github/CONTRIBUTING.md) * [x] This issue hasn't been addressed in an [existing issue](https://github.com/klaviyo/klaviyo-react-native-sdk/issues) or [pull request](https://github.com/klaviyo/klaviyo-react-native-sdk/pulls)
Description
As Expo is the default framework for React Native development this SDK should really consider supporting it.
Proposed Solution
That said, we've been recently implementing it in an Expo project and I'll share the plugin files needed to implement at least Push Open event (it may be extended to other features). Maybe it clears the path for some people who are planning to use it and make maintainers realize it is not that difficult to add out-of-the-box Expo support. withKlaviyo.js withKlaviyoIOS.js withKlaviyoAndroid.js
It may need some tweaking.
Hi Giorgio! Does your project use Expo's managed workflow? Our does, and we're also looking into using this library, so I'm trying to figure out if it will be feasible. Thanks!
@jakemadash yes, we are currently using managed workflow.
Thanks for this PR @giorgiofellipe! RNs direction is really towards using frameworks now, especially Expo. But most library providers have yet to transition
Checklist
Description
Proposed Solution
That said, we've been recently implementing it in an Expo project and I'll share the plugin files needed to implement at least Push Open event (it may be extended to other features). Maybe it clears the path for some people who are planning to use it and make maintainers realize it is not that difficult to add out-of-the-box Expo support.
withKlaviyo.js
```js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const withKlaviyoAndroid = require("./withKlaviyoAndroid").default; const withKlaviyoIOS = require("./withKlaviyoIOS").default; const withKlaviyo = expoConfig => { if (expoConfig.platforms.includes("android")) { expoConfig = withKlaviyoAndroid(expoConfig); } if (expoConfig.platforms.includes("ios")) { expoConfig = withKlaviyoIOS(expoConfig); } return expoConfig; }; exports.default = withKlaviyo; ```withKlaviyoIOS.js
```js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const { withAppDelegate, withDangerousMod } = require("@expo/config-plugins"); const fs = require("fs"); const path = require("path"); function applyiOSChanges(appDelegate) { // Add imports and implement UNUserNotificationCenterDelegate methods let imports = ` #import "ExpoModulesCore-Swift.h" #importwithKlaviyoAndroid.js
```js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const { withMainActivity } = require("@expo/config-plugins"); function applyMainActivity(mainActivity) { let klaviyoImport = "import com.klaviyo.analytics.Klaviyo\n"; let intentImport = "import android.content.Intent\n"; let firebaseTriggerImport = "import expo.modules.notifications.notifications.model.triggers.FirebaseNotificationTrigger\n"; let notificationsServiceImport = "import expo.modules.notifications.service.NotificationsService\n"; let klaviyoOnNewIntent = ` // this handler is needed in order to use it with expo-notifications, // that changes the intent extras and makes impossible to Klaviyo SDK // identify that it is a Klaviyo push private fun handleNotificationIntent(intent: Intent?): Intent? { if (intent === null) { return null } var newIntent = Intent(intent) val response = NotificationsService.getNotificationResponseFromOpenIntent(newIntent) if (response === null) { return newIntent } val KLAVIYO_PACKAGE_NAME = "com.klaviyo" val KLAVIYO_KEY = "_k" val value = (response.notification.notificationRequest.trigger as FirebaseNotificationTrigger).remoteMessage.data if (value != null && value[KLAVIYO_KEY] != null) { val extras = newIntent.extras ?: Bundle() // Initialize extras if null if (extras.getString(KLAVIYO_KEY) == null) { extras.putString(KLAVIYO_KEY, value[KLAVIYO_KEY]) } if (extras.getString("$KLAVIYO_PACKAGE_NAME.$KLAVIYO_KEY") == null) { extras.putString("$KLAVIYO_PACKAGE_NAME.$KLAVIYO_KEY", value[KLAVIYO_KEY]) } newIntent.putExtras(extras) // Apply the modified extras back to the new intent } return newIntent } override fun onNewIntent(intent: Intent?) { var newIntent = handleNotificationIntent(intent) super.onNewIntent(newIntent) Klaviyo.handlePush(newIntent) } `; // Ensure onNewIntent(intent) is called at the bottom of onCreate if (!mainActivity.includes("onNewIntent(intent)")) { mainActivity = mainActivity.replace( /super.onCreate\(null\)/, match => `${match}\n onNewIntent(intent)` ); } // Add import statements if not already present if (!mainActivity.includes(klaviyoImport)) { mainActivity = mainActivity.replace( /package [\w.]+/, match => `${match}\n${klaviyoImport}` ); } if (!mainActivity.includes(intentImport)) { mainActivity = mainActivity.replace( /package [\w.]+/, match => `${match}\n${intentImport}` ); } if (!mainActivity.includes(firebaseTriggerImport)) { mainActivity = mainActivity.replace( /package [\w.]+/, match => `${match}\n${firebaseTriggerImport}` ); } if (!mainActivity.includes(notificationsServiceImport)) { mainActivity = mainActivity.replace( /package [\w.]+/, match => `${match}\n${notificationsServiceImport}` ); } // Add onNewIntent method if not already present if (!mainActivity.includes("override fun onNewIntent(intent: Intent?)")) { mainActivity = mainActivity.replace( /class MainActivity : ReactActivity\(\) \{/, match => `${match}\n${klaviyoOnNewIntent}` ); } else { // Update existing onNewIntent method mainActivity = mainActivity.replace( /override fun onNewIntent\(intent: Intent\?\) \{[^}]*\}/, match => `${klaviyoOnNewIntent}` ); } return mainActivity; } const withKlaviyoAndroid = expoConfig => { expoConfig = withMainActivity(expoConfig, config => { config.modResults.contents = applyMainActivity(config.modResults.contents); return config; }); return expoConfig; }; exports.default = withKlaviyoAndroid; ```It may need some tweaking.