From 53ee59d54559bbdef675949dc14f58d4f61d3af2 Mon Sep 17 00:00:00 2001 From: thesunita <31236585+thesunita@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:45:01 +0530 Subject: [PATCH] fix: Android Advertising ID does not update unless app is relaunched (#1033) * fix: to show 'Queue restoration timeout' only once * fix: advertising id being sent for Android application installed events * chore: add privacy manifest file to core package * fix: events not being sent when adTrackingEnabled is false * fix: type mismatch inferred type is String? but String was expected * Revert "fix: type mismatch inferred type is String? but String was expected" This reverts commit 2b1e1fce8962a060d102e123752f3a534e8f2932. * chore: upgrade AnalyticsReactNativeExample to RN 0.76 * chore: upgrade AnalyticsReactNativeExample RN version to 0.76 * chore: removed actual write key with placeholder after testing * fix: Android Advertising ID does not update unless app is relaunched --------- Co-authored-by: Sunita Prajapati <> --- .../src/AdvertisingIdPlugin.ts | 95 ++++++++++++++----- 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/packages/plugins/plugin-advertising-id/src/AdvertisingIdPlugin.ts b/packages/plugins/plugin-advertising-id/src/AdvertisingIdPlugin.ts index 82bda03d..db2c0b93 100644 --- a/packages/plugins/plugin-advertising-id/src/AdvertisingIdPlugin.ts +++ b/packages/plugins/plugin-advertising-id/src/AdvertisingIdPlugin.ts @@ -6,6 +6,8 @@ import { ErrorType, SegmentError, SegmentEvent, + EventType, + TrackEventType, } from '@segment/analytics-react-native'; import { Platform, NativeModule } from 'react-native'; @@ -18,48 +20,91 @@ type AdvertisingIDNativeModule = NativeModule & { export class AdvertisingIdPlugin extends Plugin { type = PluginType.enrichment; queuedEvents: SegmentEvent[] = []; - advertisingId?: string = undefined; - isLimitAdTracking?: boolean = false; + advertisingId: string | undefined | null = undefined; + isLimitAdTracking?: boolean = undefined; configure(analytics: SegmentClient): void { + console.log('configure'); if (Platform.OS !== 'android') { return; } this.analytics = analytics; - // Create an array of promises for fetching advertising ID and limit ad tracking status - const advertisingIdPromise = this.fetchAdvertisingId(); - const limitAdTrackingStatusPromise = this.fetchLimitAdTrackingStatus(); - // Wait for both promises to resolve - Promise.all([advertisingIdPromise, limitAdTrackingStatusPromise]) - .then(([id, status]) => { - //handle advertisingID - if (id === null) { - // Need to check this condition - void analytics.track( - 'LimitAdTrackingEnabled (Google Play Services) is enabled' - ); - } else { - this.advertisingId = id; - } - //handle isLimitAdTrackingEnableStatus - this.isLimitAdTracking = status; - - // Call setContext after both values are available - void this.setContext(this.advertisingId, status); + this.fetchAdvertisingInfo() + .then(() => { + // Additional logic after the advertising info is fetched + this.sendQueued(); }) - .catch((error) => this.handleError(error)); + .catch((error) => { + this.handleError(error); + }); } - execute(event: SegmentEvent) { + async execute(event: SegmentEvent) { + // If advertisingId is not set, queue the event if (this.advertisingId === undefined) { this.queuedEvents.push(event); } else { + // Send event if advertisingId is available + const currentLimitAdTrackingStatus = + await this.fetchLimitAdTrackingStatus(); + if (this.isLimitAdTracking === undefined) { + this.isLimitAdTracking = currentLimitAdTrackingStatus; + } else if (this.isLimitAdTracking !== currentLimitAdTrackingStatus) { + //Fetch the fresh advertising id + await this.fetchAdvertisingInfo() + .then(() => { + console.log( + 'Advertising info fetched successfully when adTrackingStatus Changed.' + ); + // Additional logic after the advertising info is fetched + }) + .catch((error) => { + this.handleError(error); + }); + this.queuedEvents.push(event); + this.isLimitAdTracking = currentLimitAdTrackingStatus; + this.sendQueued(); + return; + } return event; } + return; } + isTrackEvent(event: SegmentEvent): event is TrackEventType { + return event.type === EventType.TrackEvent; + } + + private async fetchAdvertisingInfo(): Promise { + const advertisingIdPromise = this.fetchAdvertisingId(); + const limitAdTrackingStatusPromise = this.fetchLimitAdTrackingStatus(); + + try { + // Await both promises to resolve simultaneously + const [id, status] = await Promise.all([ + advertisingIdPromise, + limitAdTrackingStatusPromise, + ]); + + // Handle advertisingID + if (id === null) { + void this.analytics?.track( + 'LimitAdTrackingEnabled (Google Play Services) is enabled' + ); + this.advertisingId = undefined; // Set to undefined if id is null + } else { + this.advertisingId = id; + } + + // Set context after both values are available + await this.setContext(id as string, status); + } catch (error) { + this.handleError(error); + } + } + async setContext( id: string | undefined, isLimitAdTrackingEnableStatus: boolean @@ -71,7 +116,6 @@ export class AdvertisingIdPlugin extends Plugin { adTrackingEnabled: !isLimitAdTrackingEnableStatus, }, }); - this.sendQueued(); } catch (error) { const message = 'AdvertisingID failed to set context'; this.analytics?.reportInternalError( @@ -82,6 +126,7 @@ export class AdvertisingIdPlugin extends Plugin { } sendQueued() { + console.log('Sending queued events:', this.queuedEvents); this.queuedEvents.forEach((event) => { void this.analytics?.process(event); });