Skip to content

Commit

Permalink
Merge branch 'master' into ecm/reactify
Browse files Browse the repository at this point in the history
* master:
  Implemented deep links to call react native in example iOS app (#104)
  Update README.md (#105)
  Remove local.properties from git index (#96)
  Fix mistaken duplicate open push section (#95)

# Conflicts:
#	example/ios/KlaviyoReactNativeSdkExample/AppDelegate.mm
  • Loading branch information
Evan Masseau committed Feb 16, 2024
2 parents 41ca9e8 + ed9a92c commit 989af1f
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 39 deletions.
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,6 @@ parameters in the event properties. To track push opens, you will need to follow
- [Android](https://github.com/klaviyo/klaviyo-android-sdk#Tracking-Open-Events)
- [iOS](https://github.com/klaviyo/klaviyo-swift-sdk#Tracking-Open-Events)

#### Tracking Open Events
To track push notification opens, you must call `Klaviyo.handlePush(intent)` when your app is launched from an intent.
This method will check if the app was opened from a notification originating from Klaviyo and if so, create an
`Opened Push` event with required message tracking parameters. For example:

#### Deep Linking
[Deep Links](https://help.klaviyo.com/hc/en-us/articles/14750403974043) allow you to navigate to a particular
page within your app in response to the user opening a notification. Familiarize yourself with the
Expand All @@ -260,16 +255,17 @@ instructions below.
- [Android](https://github.com/klaviyo/klaviyo-android-sdk#Deep-Linking) instructions for handling intent filters
- [iOS](https://github.com/klaviyo/klaviyo-swift-sdk#Deep-Linking)
As shown in the native SDK documentation, you can follow option 1 or 2.
With option 1, when you get the callback, you can handle it as follows:

With option 1, when you handle the open url (in [`application(_:open:options)`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application)),
you call the linking code block above similar to what you would do with option 1.

With option 2, when you get the `deepLinkHandler`, you can handle it as follows:

```objective-c
[RCTLinkingManager application:application openURL:url options:options]
[RCTLinkingManager application:UIApplication.sharedApplication openURL: url options: @{}];
```

Since you won't have `options`, you can just pass in an empty dictionary for that parameter.
With option 2, when you handle the open url (in [`application(_:open:options)`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application)),
you call the linking code block above similar to what you would do with option 1.
For application, you can pass in an instance of `UIApplication` and since you won't have `options`, you can just pass in an empty dictionary for that parameter.
In your React Native code, you can handle the deep link as follows:
Expand Down
6 changes: 3 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ def localProperties = new Properties()
if (rootProject.file("local.properties").canRead()) {
localProperties.load(new FileInputStream(rootProject.file("local.properties")))
}
def reactNativeVersion = localProperties['reactNativeAndroidVersion'] ?: ""
def reactNativeAndroidVersion = localProperties['reactNativeAndroidVersion'] ?: ""


dependencies {
if (reactNativeVersion) {
if (reactNativeAndroidVersion) {
// For local development of the SDK code, specify the react-android version to use
// So that the SDK can be built and .kt files are linted against a real version of react-native
implementation "com.facebook.react:react-android:$reactNativeVersion"
implementation "com.facebook.react:react-android:$reactNativeAndroidVersion"
} else {
// Production build / once embedded in a react-native app,
// the react-native version gets loaded in from the application dependencies.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
## Changes in this file must *NOT* be tracked by Version Control Systems,
# as it contains information specific to your local configuration.
# Only the base template should be checked in to VCS.
# Copy this file to `local.properties` to set your local overrides

## Uncomment for local SDK development, so that gradle can locate the
## Used for local SDK development, so that gradle can locate the
# correct RN version outside the context of an application
#reactNativeAndroidVersion=0.73.1
reactNativeAndroidVersion=0.73.1
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
# as it contains information specific to your local configuration,
# such as your Klaviyo company ID aka "Public API Key".
# Only the base template should be checked in to VCS.
# Copy this file to `local.properties` to set your local overrides

#publicApiKey=YOUR_PUBLIC_API_KEY
publicApiKey=YOUR_PUBLIC_API_KEY
31 changes: 22 additions & 9 deletions example/ios/KlaviyoReactNativeSdkExample/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>


@implementation AppDelegate

Expand Down Expand Up @@ -31,9 +33,8 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio
[PushNotificationsHelper setPushTokenWithToken:deviceToken];

if (isDebug) {
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"Device Token: %@", token);
NSString *token = [self stringFromDeviceToken:deviceToken];
NSLog(@"Device Token: %@", token);
}
}

Expand All @@ -48,9 +49,13 @@ - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotif
// when the app is in the background
// NOTE: this delegate will NOT be called if Installation Step 2 is not done.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
// Installation Step 10: call `handleReceivingPushWithResponse` method and pass in the below arguments. Note that handleReceivingPushWithResponse calls our SDK and is
// something that has to be implemented in your app as well.
[PushNotificationsHelper handleReceivingPushWithResponse:response completionHandler:completionHandler];
// Installation Step 10: call `handleReceivingPushWithResponse` method and pass in the below arguments.
// Note that handleReceivingPushWithResponse calls our SDK and is something that has to be implemented in your app as well.
// Further, if you want to intercept urls instead of them being routed to the system and system calling `application:openURL:options:` you can implement the `deepLinkHandler` below
[PushNotificationsHelper handleReceivingPushWithResponse:response completionHandler:completionHandler deepLinkHandler:^(NSURL * _Nonnull url) {
NSLog(@"URL is %@", url);
[RCTLinkingManager application:UIApplication.sharedApplication openURL: url options: @{}];
}];

if (isDebug) {
UIAlertController *alert = [UIAlertController
Expand Down Expand Up @@ -90,12 +95,11 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center

// Installation Step 13: Implement this method to receive deep link. There are some addition setup steps needed as mentioned in the readme here -
// https://github.com/klaviyo/klaviyo-swift-sdk?tab=readme-ov-file#deep-linking
// additionally routing to the right screen in the app based on the url is also something that should be handled
// Calling `RCTLinkingManager` is required for your react native listeners to be called
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [PushNotificationsHelper handleDeepLinksWithUrl:url];
return [RCTLinkingManager application:app openURL:url options:options];
}


- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self getBundleURL];
Expand All @@ -110,4 +114,13 @@ - (NSURL *)getBundleURL
#endif
}

- (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
const unsigned char *tokenBytes = (const unsigned char *)[deviceToken bytes];
NSMutableString *token = [NSMutableString stringWithCapacity:([deviceToken length] * 2)];
for (NSUInteger i = 0; i < [deviceToken length]; i++) {
[token appendFormat:@"%02x", tokenBytes[i]];
}
return token;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,18 @@ class PushNotificationsHelper: NSObject {
}

@objc
static func handleReceivingPush(response: UNNotificationResponse, completionHandler: @escaping () -> Void ) {
let handled = KlaviyoSDK().handle(notificationResponse: response, withCompletionHandler: completionHandler)
static func handleReceivingPush(
response: UNNotificationResponse,
completionHandler: @escaping () -> Void,
deepLinkHandler: ((URL) -> Void)? = nil
) {
let handled = KlaviyoSDK().handle(
notificationResponse: response,
withCompletionHandler: completionHandler,
deepLinkHandler: deepLinkHandler
)
if !handled {
completionHandler()
}
}

@objc
static func handleDeepLinks(url: URL) -> Bool {
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true)
else {
print("Invalid deep linking URL")
return false
}
print("components: \(components.debugDescription)")
return true
}
}
12 changes: 12 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import * as React from 'react';

import { useEffect } from 'react';

import { Button, View } from 'react-native';
import { type AppViewInterface, appViews } from './AppViewInterface';
import { styles } from './Styles';
import { Linking } from 'react-native';

export default function App() {
useEffect(() => {
Linking.addEventListener('url', ({ url }) => {
console.log('Event Listener: url', url);
});
Linking.getInitialURL().then((url) => {
console.log('Initial Url: url', url);
});
}, []);

return (
<View style={styles.container}>
<>
Expand Down

0 comments on commit 989af1f

Please sign in to comment.