From e5173f78f1ad493edc8eb154804bc6fc2fc40eb2 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:59:37 +0200 Subject: [PATCH] fix: session replay plugin isn't properly identifying users already identified (#3) --- CHANGELOG.md | 2 ++ android/build.gradle | 2 +- .../PosthogReactNativeSessionReplayModule.kt | 33 +++++++++++++++---- .../project.pbxproj | 10 ++++-- ios/PosthogReactNativeSessionReplay.mm | 9 ++--- ios/PosthogReactNativeSessionReplay.swift | 33 ++++++++++++++++--- src/index.tsx | 14 +++++--- 7 files changed, 80 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0082dca..66c98e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Next +- fix: session replay plugin isn't properly identifying users already identified + ## 0.1.0 - 2024-09-19 - first minor release for React Native Session Replay \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 322fdd2..9bf2586 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -95,6 +95,6 @@ dependencies { //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "com.posthog:posthog-android:3.7.3" + implementation "com.posthog:posthog-android:3.7.4" } diff --git a/android/src/main/java/com/posthogreactnativesessionreplay/PosthogReactNativeSessionReplayModule.kt b/android/src/main/java/com/posthogreactnativesessionreplay/PosthogReactNativeSessionReplayModule.kt index e04efcc..27543c7 100644 --- a/android/src/main/java/com/posthogreactnativesessionreplay/PosthogReactNativeSessionReplayModule.kt +++ b/android/src/main/java/com/posthogreactnativesessionreplay/PosthogReactNativeSessionReplayModule.kt @@ -10,6 +10,9 @@ import com.posthog.PostHog import com.posthog.PostHogConfig import com.posthog.android.PostHogAndroid import com.posthog.android.PostHogAndroidConfig +import com.posthog.internal.PostHogPreferences +import com.posthog.internal.PostHogPreferences.Companion.ANONYMOUS_ID +import com.posthog.internal.PostHogPreferences.Companion.DISTINCT_ID import com.posthog.internal.PostHogSessionManager import java.util.UUID @@ -20,13 +23,6 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex return NAME } - // Example method - // See https://reactnative.dev/docs/native-modules-android - @ReactMethod - fun multiply(a: Double, b: Double, promise: Promise) { - promise.resolve(a * b) - } - @ReactMethod fun start(sessionId: String, sdkOptions: ReadableMap, sdkReplayConfig: ReadableMap, decideReplayConfig: ReadableMap, promise: Promise) { val uuid = UUID.fromString(sessionId) @@ -44,6 +40,9 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex val endpoint = decideReplayConfig.getString("endpoint") + val distinctId = sdkOptions.getString("distinctId") ?: "" + val anonymousId = sdkOptions.getString("anonymousId") ?: "" + val config = PostHogAndroidConfig(apiKey, host).apply { debug = debugValue captureDeepLinks = false @@ -62,6 +61,8 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex } PostHogAndroid.setup(context, config) + setIdentify(config.cachePreferences, distinctId, anonymousId) + promise.resolve(null) } @@ -84,6 +85,24 @@ class PosthogReactNativeSessionReplayModule(reactContext: ReactApplicationContex promise.resolve(null) } + @ReactMethod + fun identify(distinctId: String, anonymousId: String, promise: Promise) { + setIdentify(PostHog.getConfig()?.cachePreferences, distinctId, anonymousId) + + promise.resolve(null) + } + + private fun setIdentify(cachePreferences: PostHogPreferences?, distinctId: String, anonymousId: String) { + cachePreferences?.let { preferences -> + if (anonymousId.isNotEmpty()) { + preferences.setValue(ANONYMOUS_ID, anonymousId) + } + if (distinctId.isNotEmpty()) { + preferences.setValue(DISTINCT_ID, distinctId) + } + } + } + companion object { const val NAME = "PosthogReactNativeSessionReplay" } diff --git a/example/ios/PosthogReactNativeSessionReplayExample.xcodeproj/project.pbxproj b/example/ios/PosthogReactNativeSessionReplayExample.xcodeproj/project.pbxproj index 172291e..d67d378 100644 --- a/example/ios/PosthogReactNativeSessionReplayExample.xcodeproj/project.pbxproj +++ b/example/ios/PosthogReactNativeSessionReplayExample.xcodeproj/project.pbxproj @@ -610,7 +610,10 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -683,7 +686,10 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/ios/PosthogReactNativeSessionReplay.mm b/ios/PosthogReactNativeSessionReplay.mm index 3b8f454..efe04f7 100644 --- a/ios/PosthogReactNativeSessionReplay.mm +++ b/ios/PosthogReactNativeSessionReplay.mm @@ -2,10 +2,6 @@ @interface RCT_EXTERN_MODULE(PosthogReactNativeSessionReplay, NSObject) -RCT_EXTERN_METHOD(multiply:(float)a withB:(float)b - withResolver:(RCTPromiseResolveBlock)resolve - withRejecter:(RCTPromiseRejectBlock)reject) - RCT_EXTERN_METHOD(start:(NSString)sessionId withSdkOptions:(NSDictionary)sdkOptions withSdkReplayConfig:(NSDictionary)sdkReplayConfig @@ -23,6 +19,11 @@ @interface RCT_EXTERN_MODULE(PosthogReactNativeSessionReplay, NSObject) RCT_EXTERN_METHOD(endSession:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(identify:(NSString)distinctId + withAnonymousId:(NSString)anonymousId + withResolver:(RCTPromiseResolveBlock)resolve + withRejecter:(RCTPromiseRejectBlock)reject) + + (BOOL)requiresMainQueueSetup { return NO; diff --git a/ios/PosthogReactNativeSessionReplay.swift b/ios/PosthogReactNativeSessionReplay.swift index 3c61e8f..bf3951c 100644 --- a/ios/PosthogReactNativeSessionReplay.swift +++ b/ios/PosthogReactNativeSessionReplay.swift @@ -3,11 +3,8 @@ import PostHog @objc(PosthogReactNativeSessionReplay) class PosthogReactNativeSessionReplay: NSObject { - @objc(multiply:withB:withResolver:withRejecter:) - func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { - resolve(a*b) - } - + private var config: PostHogConfig? + @objc(start:withSdkOptions:withSdkReplayConfig:withDecideReplayConfig:withResolver:withRejecter:) func start(sessionId: String, sdkOptions: [String: Any], sdkReplayConfig: [String: Any], decideReplayConfig: [String: Any], resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) { let apiKey = sdkOptions["apiKey"] as? String ?? "" @@ -41,8 +38,15 @@ class PosthogReactNativeSessionReplay: NSObject { config.snapshotEndpoint = endpoint } + let distinctId = sdkOptions["distinctId"] as? String ?? "" + let anonymousId = sdkOptions["anonymousId"] as? String ?? "" + PostHogSDK.shared.setup(config) + self.config = config + + setIdentify(self.config?.storageManager, distinctId: distinctId, anonymousId: anonymousId) + resolve(nil) } @@ -64,4 +68,23 @@ class PosthogReactNativeSessionReplay: NSObject { PostHogSDK.shared.endSession() resolve(nil) } + + @objc(identify:withAnonymousId:withResolver:withRejecter:) + func identify(distinctId: String, anonymousId: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { + setIdentify(self.config?.storageManager, distinctId: distinctId, anonymousId: anonymousId) + + resolve(nil) + } + + private func setIdentify(_ storageManager: PostHogStorageManager?, distinctId: String, anonymousId: String) { + guard let storageManager = storageManager else { + return + } + if !anonymousId.isEmpty { + storageManager.setAnonymousId(anonymousId) + } + if !distinctId.isEmpty { + storageManager.setDistinctId(distinctId) + } + } } diff --git a/src/index.tsx b/src/index.tsx index 9a9e5ff..b10b382 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -18,10 +18,6 @@ const PosthogReactNativeSessionReplay = } ); -export function multiply(a: number, b: number): Promise { - return PosthogReactNativeSessionReplay.multiply(a, b); -} - export function start( sessionId: string, sdkOptions: { [key: string]: any }, @@ -48,6 +44,13 @@ export function isEnabled(): Promise { return PosthogReactNativeSessionReplay.isEnabled(); } +export function identify( + distinctId: string, + anonymousId: string +): Promise { + return PosthogReactNativeSessionReplay.identify(distinctId, anonymousId); +} + export interface PostHogReactNativeSessionReplayModule { start: ( sessionId: string, @@ -61,6 +64,8 @@ export interface PostHogReactNativeSessionReplayModule { endSession: () => Promise; isEnabled: () => Promise; + + identify: (distinctId: string, anonymousId: string) => Promise; } const PostHogReactNativeSessionReplay: PostHogReactNativeSessionReplayModule = { @@ -68,6 +73,7 @@ const PostHogReactNativeSessionReplay: PostHogReactNativeSessionReplayModule = { startSession, endSession, isEnabled, + identify, }; export default PostHogReactNativeSessionReplay;