1- // import {
2- // EventPlugin,
3- // EventType,
4- // IdentifyEventType,
5- // PluginType,
6- // SegmentAPISettings,
7- // SegmentEvent,
8- // TrackEventType,
9- // ScreenEventType,
10- // GroupEventType,
11- // UpdateType,
12- // AliasEventType,
13- // SegmentClient,
14- // } from '@segment/analytics-react-native';
15-
16- // const MAX_SESSION_TIME_IN_MS = 300000;
17- // export class AmplitudeSessionPlugin extends EventPlugin {
18- // type = PluginType.enrichment;
19- // key = 'Actions Amplitude';
20- // active = false;
21- // sessionId: number | undefined;
22- // sessionTimer: ReturnType<typeof setTimeout> | undefined;
23-
24- // configure(_analytics: SegmentClient): void {
25- // this.analytics = _analytics;
26- // }
27-
28- // update(settings: SegmentAPISettings, _: UpdateType) {
29- // const integrations = settings.integrations;
30- // if (this.key in integrations) {
31- // this.active = true;
32- // this.refreshSession();
33- // }
34- // }
35-
36- // execute(event: SegmentEvent) {
37- // if (!this.active) {
38- // return event;
39- // }
40-
41- // this.refreshSession();
42-
43- // let result = event;
44- // switch (result.type) {
45- // case EventType.IdentifyEvent:
46- // result = this.identify(result);
47- // break;
48- // case EventType.TrackEvent:
49- // result = this.track(result);
50- // break;
51- // case EventType.ScreenEvent:
52- // result = this.screen(result);
53- // break;
54- // case EventType.AliasEvent:
55- // result = this.alias(result);
56- // break;
57- // case EventType.GroupEvent:
58- // result = this.group(result);
59- // break;
60- // }
61- // return result;
62- // }
63-
64- // identify(event: IdentifyEventType) {
65- // return this.insertSession(event) as IdentifyEventType;
66- // }
67-
68- // track(event: TrackEventType) {
69- // return this.insertSession(event) as TrackEventType;
70- // }
71-
72- // screen(event: ScreenEventType) {
73- // return this.insertSession(event) as ScreenEventType;
74- // }
75-
76- // group(event: GroupEventType) {
77- // return this.insertSession(event) as GroupEventType;
78- // }
79-
80- // alias(event: AliasEventType) {
81- // return this.insertSession(event) as AliasEventType;
82- // }
83-
84- // reset() {
85- // this.resetSession();
86- // }
87-
88- // private insertSession = (event: SegmentEvent) => {
89- // const returnEvent = event;
90- // const integrations = event.integrations;
91- // returnEvent.integrations = {
92- // ...integrations,
93- // [this.key]: {
94- // session_id: this.sessionId,
95- // },
96- // };
97- // return returnEvent;
98- // };
99-
100- // private resetSession = () => {
101- // this.sessionId = Date.now();
102- // this.sessionTimer = undefined;
103- // };
104-
105- // private refreshSession = () => {
106- // if (this.sessionId === undefined) {
107- // this.sessionId = Date.now();
108- // }
109-
110- // if (this.sessionTimer !== undefined) {
111- // clearTimeout(this.sessionTimer);
112- // }
113-
114- // this.sessionTimer = setTimeout(
115- // () => this.resetSession(),
116- // MAX_SESSION_TIME_IN_MS
117- // );
118- // };
119- // }
120-
1211import {
1222 EventPlugin ,
1233 EventType ,
@@ -135,43 +15,51 @@ import {
13515
13616import AsyncStorage from '@react-native-async-storage/async-storage' ;
13717import { AppState } from 'react-native' ;
18+ //import { AppState } from 'react-native';
13819
13920const MAX_SESSION_TIME_IN_MS = 300000 ;
140- const SESSION_ID_KEY = 'amplitude_session_id' ;
141- const LAST_EVENT_TIME_KEY = 'amplitude_last_event_time' ;
21+ const SESSION_ID_KEY = 'previous_session_id' ;
22+ const LAST_EVENT_TIME_KEY = 'last_event_time' ;
23+ const AMP_SESSION_START_EVENT = 'session_start' ;
24+ const AMP_SESSION_END_EVENT = 'session_end' ;
14225
14326export class AmplitudeSessionPlugin extends EventPlugin {
14427 type = PluginType . enrichment ;
14528 key = 'Actions Amplitude' ;
14629 active = false ;
147- sessionId : number | undefined ;
148- lastEventTime : number | undefined ;
30+ sessionId = - 1 ;
31+ lastEventTime = - 1 ;
14932 sessionTimer : ReturnType < typeof setTimeout > | undefined ;
15033
151- configure ( _analytics : SegmentClient ) : void {
152- this . analytics = _analytics ;
34+ configure ( analytics : SegmentClient ) : void {
35+ this . analytics = analytics ;
15336 AppState . addEventListener ( 'change' , this . handleAppStateChange ) ;
15437 this . loadSessionData ( ) ;
38+ if ( this . sessionId === - 1 ) {
39+ this . startNewSession ( ) ;
40+ } else {
41+ this . startNewSessionIfNecessary ( ) ;
42+ }
15543 }
15644
157- // Called when plugin is initialized with Segment settings
158- update ( settings : SegmentAPISettings , _ : UpdateType ) {
159- const integrations = settings . integrations ;
160- if ( this . key in integrations ) {
161- this . active = true ;
162- this . refreshSession ( ) ;
45+ update ( settings : SegmentAPISettings , type : UpdateType ) {
46+ if ( type !== UpdateType . initial ) {
47+ return ;
16348 }
49+ this . active = settings . integrations ?. hasOwnProperty ( this . key ) ?? false ;
16450 }
16551
166- // Core event processing hook
16752 async execute ( event : SegmentEvent ) {
16853 if ( ! this . active ) {
16954 return event ;
17055 }
171-
172- await this . refreshSession ( ) ;
56+ await this . startNewSessionIfNecessary ( ) ;
17357
17458 let result = event ;
59+ if ( result . type === EventType . TrackEvent ) {
60+ console . log ( result . event ) ;
61+ }
62+
17563 switch ( result . type ) {
17664 case EventType . IdentifyEvent :
17765 result = this . identify ( result ) ;
@@ -189,6 +77,10 @@ export class AmplitudeSessionPlugin extends EventPlugin {
18977 result = this . group ( result ) ;
19078 break ;
19179 }
80+
81+ this . lastEventTime = Date . now ( ) ;
82+ await this . saveSessionData ( ) ;
83+
19284 return result ;
19385 }
19486
@@ -201,6 +93,10 @@ export class AmplitudeSessionPlugin extends EventPlugin {
20193 }
20294
20395 screen ( event : ScreenEventType ) {
96+ event . properties = {
97+ ...event . properties ,
98+ name : event . name ,
99+ } ;
204100 return this . insertSession ( event ) as ScreenEventType ;
205101 }
206102
@@ -213,103 +109,99 @@ export class AmplitudeSessionPlugin extends EventPlugin {
213109 }
214110
215111 reset ( ) {
216- this . resetSession ( ) ;
112+ // this.resetSession();
217113 }
218114
219- // Injects session_id into event's integrations
220115 private insertSession = ( event : SegmentEvent ) => {
221116 const returnEvent = event ;
117+ const integrations = event . integrations || { } ;
118+ const existingIntegration = integrations [ this . key ] ;
119+ const hasSessionId =
120+ typeof existingIntegration === 'object' &&
121+ existingIntegration !== null &&
122+ 'session_id' in existingIntegration ;
123+
124+ // If session_id exists, return as is
125+ if ( hasSessionId ) {
126+ return returnEvent ;
127+ }
128+
222129 returnEvent . integrations = {
223- ...event . integrations ,
130+ ...integrations ,
224131 [ this . key ] : {
225132 session_id : this . sessionId ,
226133 } ,
227134 } ;
228135 return returnEvent ;
229136 } ;
230137
231- // Emits session start/end events manually (optional for debugging or analytics)
232- private trackSessionEvent = ( eventName : string ) => {
233- if ( this . analytics && this . sessionId != null ) {
234- this . analytics . track ( eventName , {
138+ private onBackground ( ) {
139+ this . lastEventTime = Date . now ( ) ;
140+
141+ this . saveSessionData ( ) ;
142+ }
143+
144+ private onForeground ( ) {
145+ this . startNewSessionIfNecessary ( ) ;
146+ }
147+
148+ private async startNewSessionIfNecessary ( ) {
149+ const current = Date . now ( ) ;
150+ const withinSessionLimit =
151+ current - this . lastEventTime < MAX_SESSION_TIME_IN_MS ;
152+ if ( this . sessionId >= 0 && withinSessionLimit ) {
153+ return ;
154+ }
155+ this . lastEventTime = current ;
156+ await this . endSession ( ) ;
157+ await this . startNewSession ( ) ;
158+ }
159+
160+ private async startNewSession ( ) {
161+ this . sessionId = Date . now ( ) ;
162+ const copy = this . sessionId ;
163+ if ( this . analytics ) {
164+ this . analytics . track ( AMP_SESSION_START_EVENT , {
235165 integrations : {
236- [ this . key ] : {
237- session_id : this . sessionId ,
238- } ,
166+ [ this . key ] : { session_id : copy } ,
239167 } ,
240168 } ) ;
241169 }
242- } ;
243-
244- // Creates new session and tracks it
245- private resetSession = async ( ) => {
246- this . trackSessionEvent ( 'session_end' ) ;
247- this . sessionId = Date . now ( ) ;
248- this . lastEventTime = this . sessionId ;
249- this . trackSessionEvent ( 'session_start' ) ;
250- this . sessionTimer = undefined ;
251170 await this . saveSessionData ( ) ;
252- } ;
253-
254- // Refreshes session only if session timeout occurred
255- private refreshSession = async ( ) => {
256- const now = Date . now ( ) ;
257- console . log ( 'sessionId' , this . sessionId ) ;
258- console . log ( 'this.lastEventTime' , this . lastEventTime ) ;
259- if ( this . lastEventTime != null ) {
260- console . log (
261- 'now - this.lastEventTime > MAX_SESSION_TIME_IN_MS' ,
262- now - this . lastEventTime > MAX_SESSION_TIME_IN_MS
263- ) ;
264- }
265- if (
266- this . sessionId === undefined ||
267- this . lastEventTime === undefined ||
268- now - this . lastEventTime > MAX_SESSION_TIME_IN_MS
269- ) {
270- console . log ( ' await this.resetSession()' ) ;
271- await this . resetSession ( ) ;
272- } else {
273- this . lastEventTime = now ;
274- console . log ( ' await this.saveSessionData()' ) ;
275- await this . saveSessionData ( ) ;
276- }
171+ }
277172
278- if ( this . sessionTimer !== undefined ) {
279- clearTimeout ( this . sessionTimer ) ;
173+ private async endSession ( ) {
174+ const copy = this . sessionId ;
175+ if ( this . analytics ) {
176+ this . analytics . track ( AMP_SESSION_END_EVENT , {
177+ integrations : {
178+ [ this . key ] : { session_id : copy } ,
179+ } ,
180+ } ) ;
280181 }
182+ }
281183
282- this . sessionTimer = setTimeout (
283- ( ) => this . resetSession ( ) ,
284- MAX_SESSION_TIME_IN_MS
285- ) ;
286- } ;
287-
288- // Loads stored session state from persistent storage
289184 private async loadSessionData ( ) {
290185 const storedSessionId = await AsyncStorage . getItem ( SESSION_ID_KEY ) ;
291186 const storedLastEventTime = await AsyncStorage . getItem ( LAST_EVENT_TIME_KEY ) ;
292- this . sessionId =
293- storedSessionId != null ? Number ( storedSessionId ) : undefined ;
187+ this . sessionId = storedSessionId != null ? Number ( storedSessionId ) : - 1 ;
294188 this . lastEventTime =
295- storedLastEventTime != null ? Number ( storedLastEventTime ) : undefined ;
189+ storedLastEventTime != null ? Number ( storedLastEventTime ) : - 1 ;
296190 }
297191
298- // Persists session state
299192 private async saveSessionData ( ) {
300- if ( this . sessionId !== undefined ) {
301- await AsyncStorage . setItem ( SESSION_ID_KEY , this . sessionId . toString ( ) ) ;
302- await AsyncStorage . setItem ( LAST_EVENT_TIME_KEY , Date . now ( ) . toString ( ) ) ;
303- }
193+ await AsyncStorage . setItem ( SESSION_ID_KEY , this . sessionId . toString ( ) ) ;
194+ await AsyncStorage . setItem (
195+ LAST_EVENT_TIME_KEY ,
196+ this . lastEventTime . toString ( )
197+ ) ;
304198 }
305199
306- // Handles app going to foreground/background
307200 private handleAppStateChange = ( nextAppState : string ) => {
308- console . log ( 'nextAppState' , nextAppState ) ;
309201 if ( nextAppState === 'active' ) {
310- this . refreshSession ( ) ;
202+ this . onForeground ( ) ;
311203 } else if ( nextAppState === 'background' ) {
312- this . saveSessionData ( ) ;
204+ this . onBackground ( ) ;
313205 }
314206 } ;
315207}
0 commit comments