-
Notifications
You must be signed in to change notification settings - Fork 222
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add internal session plugin to the React Native tracker (#1388)
- Loading branch information
1 parent
f0b7c80
commit 939388c
Showing
24 changed files
with
632 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
...s/react-native-tracker/markdown/react-native-tracker.sessionstate.eventindex.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [eventIndex](./react-native-tracker.sessionstate.eventindex.md) | ||
|
||
## SessionState.eventIndex property | ||
|
||
Optional index of the current event in the session | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
eventIndex?: number; | ||
``` |
13 changes: 13 additions & 0 deletions
13
...react-native-tracker/markdown/react-native-tracker.sessionstate.firsteventid.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [firstEventId](./react-native-tracker.sessionstate.firsteventid.md) | ||
|
||
## SessionState.firstEventId property | ||
|
||
The optional identifier of the first event for this session | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
firstEventId?: string; | ||
``` |
13 changes: 13 additions & 0 deletions
13
...ative-tracker/markdown/react-native-tracker.sessionstate.firsteventtimestamp.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [firstEventTimestamp](./react-native-tracker.sessionstate.firsteventtimestamp.md) | ||
|
||
## SessionState.firstEventTimestamp property | ||
|
||
Optional date-time timestamp of when the first event in the session was tracked | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
firstEventTimestamp?: string; | ||
``` |
27 changes: 27 additions & 0 deletions
27
api-docs/docs/react-native-tracker/markdown/react-native-tracker.sessionstate.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) | ||
|
||
## SessionState interface | ||
|
||
Current session state that is tracked in events. | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
export interface SessionState | ||
``` | ||
|
||
## Properties | ||
|
||
| Property | Type | Description | | ||
| --- | --- | --- | | ||
| [eventIndex?](./react-native-tracker.sessionstate.eventindex.md) | number | <i>(Optional)</i> Optional index of the current event in the session | | ||
| [firstEventId?](./react-native-tracker.sessionstate.firsteventid.md) | string | <i>(Optional)</i> The optional identifier of the first event for this session | | ||
| [firstEventTimestamp?](./react-native-tracker.sessionstate.firsteventtimestamp.md) | string | <i>(Optional)</i> Optional date-time timestamp of when the first event in the session was tracked | | ||
| [previousSessionId?](./react-native-tracker.sessionstate.previoussessionid.md) | string | <i>(Optional)</i> The previous session identifier for this user | | ||
| [sessionId](./react-native-tracker.sessionstate.sessionid.md) | string | An identifier for the session | | ||
| [sessionIndex](./react-native-tracker.sessionstate.sessionindex.md) | number | The index of the current session for this user | | ||
| [storageMechanism](./react-native-tracker.sessionstate.storagemechanism.md) | string | The mechanism that the session information has been stored on the device | | ||
| [userId](./react-native-tracker.sessionstate.userid.md) | string | An identifier for the user of the session | | ||
|
13 changes: 13 additions & 0 deletions
13
...-native-tracker/markdown/react-native-tracker.sessionstate.previoussessionid.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [previousSessionId](./react-native-tracker.sessionstate.previoussessionid.md) | ||
|
||
## SessionState.previousSessionId property | ||
|
||
The previous session identifier for this user | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
previousSessionId?: string; | ||
``` |
13 changes: 13 additions & 0 deletions
13
...cs/react-native-tracker/markdown/react-native-tracker.sessionstate.sessionid.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [sessionId](./react-native-tracker.sessionstate.sessionid.md) | ||
|
||
## SessionState.sessionId property | ||
|
||
An identifier for the session | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
sessionId: string; | ||
``` |
13 changes: 13 additions & 0 deletions
13
...react-native-tracker/markdown/react-native-tracker.sessionstate.sessionindex.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [sessionIndex](./react-native-tracker.sessionstate.sessionindex.md) | ||
|
||
## SessionState.sessionIndex property | ||
|
||
The index of the current session for this user | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
sessionIndex: number; | ||
``` |
13 changes: 13 additions & 0 deletions
13
...t-native-tracker/markdown/react-native-tracker.sessionstate.storagemechanism.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [storageMechanism](./react-native-tracker.sessionstate.storagemechanism.md) | ||
|
||
## SessionState.storageMechanism property | ||
|
||
The mechanism that the session information has been stored on the device | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
storageMechanism: string; | ||
``` |
13 changes: 13 additions & 0 deletions
13
.../docs/react-native-tracker/markdown/react-native-tracker.sessionstate.userid.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!-- Do not edit this file. It is automatically generated by API Documenter. --> | ||
|
||
[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [SessionState](./react-native-tracker.sessionstate.md) > [userId](./react-native-tracker.sessionstate.userid.md) | ||
|
||
## SessionState.userId property | ||
|
||
An identifier for the user of the session | ||
|
||
<b>Signature:</b> | ||
|
||
```typescript | ||
userId: string; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
...n/changes/@snowplow/react-native-tracker/issue-react_native_session_2024-11-21-13-47.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"changes": [ | ||
{ | ||
"packageName": "@snowplow/react-native-tracker", | ||
"comment": "Add internal session plugin to the React Native tracker (#1388)", | ||
"type": "none" | ||
} | ||
], | ||
"packageName": "@snowplow/react-native-tracker" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. | ||
{ | ||
"pnpmShrinkwrapHash": "8169e5436cbe751223029ee55f3f12295943b739", | ||
"pnpmShrinkwrapHash": "50fa04b4f2a1f9fdbf83a84ce901759859832bfd", | ||
"preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const FOREGROUND_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/application_foreground/jsonschema/1-0-0'; | ||
export const BACKGROUND_EVENT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/application_background/jsonschema/1-0-0'; | ||
|
||
export const CLIENT_SESSION_ENTITY_SCHEMA ='iglu:com.snowplowanalytics.snowplow/client_session/jsonschema/1-0-2' |
124 changes: 124 additions & 0 deletions
124
trackers/react-native-tracker/src/plugins/session/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { CorePluginConfiguration, PayloadBuilder } from '@snowplow/tracker-core'; | ||
import { SessionConfiguration, SessionState, TrackerConfiguration } from '../../types'; | ||
import AsyncStorage from '@react-native-async-storage/async-storage'; | ||
import { v4 as uuidv4 } from 'uuid'; | ||
import { BACKGROUND_EVENT_SCHEMA, CLIENT_SESSION_ENTITY_SCHEMA, FOREGROUND_EVENT_SCHEMA } from '../../constants'; | ||
import { getUsefulSchema } from '../../utils'; | ||
|
||
interface StoredSessionState { | ||
userId: string; | ||
sessionId: string; | ||
sessionIndex: number; | ||
} | ||
|
||
interface SessionPlugin extends CorePluginConfiguration { | ||
getSessionUserId: () => Promise<string | undefined>; | ||
getSessionId: () => Promise<string | undefined>; | ||
getSessionIndex: () => Promise<number | undefined>; | ||
getSessionState: () => Promise<SessionState>; | ||
startNewSession: () => Promise<void>; | ||
} | ||
|
||
async function storeSessionState(namespace: string, state: StoredSessionState) { | ||
const { userId, sessionId, sessionIndex } = state; | ||
await AsyncStorage.setItem(`snowplow_${namespace}_session`, JSON.stringify({ userId, sessionId, sessionIndex })); | ||
} | ||
|
||
async function resumeStoredSession(namespace: string): Promise<SessionState> { | ||
const storedState = await AsyncStorage.getItem(`snowplow_${namespace}_session`); | ||
if (storedState) { | ||
const state = JSON.parse(storedState) as StoredSessionState; | ||
return { | ||
userId: state.userId, | ||
sessionId: uuidv4(), | ||
previousSessionId: state.sessionId, | ||
sessionIndex: state.sessionIndex + 1, | ||
storageMechanism: 'LOCAL_STORAGE', | ||
}; | ||
} else { | ||
return { | ||
userId: uuidv4(), | ||
sessionId: uuidv4(), | ||
sessionIndex: 1, | ||
storageMechanism: 'LOCAL_STORAGE', | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* Creates a new session plugin for tracking the session information. | ||
* The plugin will add the session context to all events and start a new session if the current one has timed out. | ||
* | ||
* The session state is stored in AsyncStorage. | ||
* Each restart of the app or creation of a new tracker instance will trigger a new session with reference to the previous session. | ||
*/ | ||
export async function newSessionPlugin({ | ||
namespace, | ||
foregroundSessionTimeout, | ||
backgroundSessionTimeout, | ||
}: TrackerConfiguration & SessionConfiguration): Promise<SessionPlugin> { | ||
let sessionState = await resumeStoredSession(namespace); | ||
await storeSessionState(namespace, sessionState); | ||
|
||
let inBackground = false; | ||
let lastUpdateTs = new Date().getTime(); | ||
|
||
const startNewSession = async () => { | ||
sessionState = { | ||
userId: sessionState.userId, | ||
storageMechanism: sessionState.storageMechanism, | ||
sessionId: uuidv4(), | ||
sessionIndex: sessionState.sessionIndex + 1, | ||
previousSessionId: sessionState.sessionId, | ||
}; | ||
}; | ||
|
||
const getTimeoutMs = () => { | ||
return ((inBackground ? backgroundSessionTimeout : foregroundSessionTimeout) ?? 30 * 60) * 1000; | ||
}; | ||
|
||
const beforeTrack = (payloadBuilder: PayloadBuilder) => { | ||
// check if session has timed out and start a new one if necessary | ||
const now = new Date(); | ||
const timeDiff = now.getTime() - lastUpdateTs; | ||
if (timeDiff > getTimeoutMs()) { | ||
startNewSession(); | ||
storeSessionState(namespace, sessionState); | ||
} | ||
lastUpdateTs = now.getTime(); | ||
|
||
// update event properties | ||
sessionState.eventIndex = (sessionState.eventIndex ?? 0) + 1; | ||
if (sessionState.eventIndex === 1) { | ||
sessionState.firstEventId = payloadBuilder.getPayload().eid as string; | ||
sessionState.firstEventTimestamp = now.toISOString(); | ||
} | ||
|
||
// update background state | ||
if (payloadBuilder.getPayload().e === 'ue') { | ||
const schema = getUsefulSchema(payloadBuilder); | ||
if (schema === FOREGROUND_EVENT_SCHEMA) { | ||
inBackground = false; | ||
} else if (schema === BACKGROUND_EVENT_SCHEMA) { | ||
inBackground = true; | ||
} | ||
} | ||
|
||
// add session context to the payload | ||
payloadBuilder.addContextEntity({ | ||
schema: CLIENT_SESSION_ENTITY_SCHEMA, | ||
data: { ...sessionState }, | ||
}); | ||
}; | ||
|
||
return { | ||
getSessionUserId: () => Promise.resolve(sessionState.userId), | ||
getSessionId: () => Promise.resolve(sessionState.sessionId), | ||
getSessionIndex: () => Promise.resolve(sessionState.sessionIndex), | ||
getSessionState: () => Promise.resolve(sessionState), | ||
startNewSession, | ||
plugin: { | ||
beforeTrack, | ||
}, | ||
}; | ||
} |
Oops, something went wrong.