From 584a62b8d8fce032192a433f163eaccb9b6862c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matu=CC=81s=CC=8C=20Tomlein?= Date: Thu, 28 Nov 2024 10:45:12 +0100 Subject: [PATCH] Add a platform context plugin to the React Native tracker to track device information --- .../markdown/react-native-tracker.md | 3 + .../react-native-tracker.newtracker.md | 4 +- ...ve-tracker.platformcontextconfiguration.md | 20 ++ ...ormcontextconfiguration.platformcontext.md | 13 + ...configuration.platformcontextproperties.md | 13 + ...tconfiguration.platformcontextretriever.md | 13 + ...-native-tracker.platformcontextproperty.md | 37 ++ ...platformcontextretriever.getandroididfa.md | 13 + ...mcontextretriever.getappavailablememory.md | 13 + ...r.platformcontextretriever.getappleidfa.md | 13 + ...r.platformcontextretriever.getappleidfv.md | 13 + ...er.platformcontextretriever.getappsetid.md | 13 + ...atformcontextretriever.getappsetidscope.md | 13 + ...ormcontextretriever.getavailablestorage.md | 13 + ...latformcontextretriever.getbatterylevel.md | 13 + ...latformcontextretriever.getbatterystate.md | 13 + ...ker.platformcontextretriever.getcarrier.md | 13 + ...mcontextretriever.getdevicemanufacturer.md | 13 + ...platformcontextretriever.getdevicemodel.md | 13 + ...er.platformcontextretriever.getlanguage.md | 13 + ...latformcontextretriever.getlowpowermode.md | 13 + ...rmcontextretriever.getnetworktechnology.md | 13 + ...platformcontextretriever.getnetworktype.md | 13 + ...cker.platformcontextretriever.getostype.md | 13 + ...r.platformcontextretriever.getosversion.md | 13 + ...tformcontextretriever.getphysicalmemory.md | 13 + ....platformcontextretriever.getresolution.md | 13 + ...acker.platformcontextretriever.getscale.md | 13 + ...ntextretriever.getsystemavailablememory.md | 13 + ...latformcontextretriever.gettotalstorage.md | 13 + ...ker.platformcontextretriever.isportrait.md | 13 + ...native-tracker.platformcontextretriever.md | 43 +++ ...react-native-tracker.reactnativetracker.md | 3 + .../react-native-tracker.api.md | 64 +++- .../react-native-tracker/src/constants.ts | 1 + .../src/plugins/platform_context/index.ts | 327 ++++++++++++++++++ trackers/react-native-tracker/src/tracker.ts | 11 +- trackers/react-native-tracker/src/types.ts | 213 ++++++++++++ .../plugins/platform_context_android.test.ts | 50 +++ .../test/plugins/platform_context_ios.test.ts | 162 +++++++++ .../react-native-tracker/test/tracker.test.ts | 54 ++- 41 files changed, 1335 insertions(+), 8 deletions(-) create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontext.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextproperties.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextretriever.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextproperty.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getandroididfa.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappavailablememory.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfa.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfv.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetid.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetidscope.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getavailablestorage.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterylevel.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterystate.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getcarrier.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemanufacturer.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemodel.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlanguage.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlowpowermode.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktechnology.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktype.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getostype.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getosversion.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getphysicalmemory.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getresolution.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getscale.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getsystemavailablememory.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.gettotalstorage.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.isportrait.md create mode 100644 api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.md create mode 100644 trackers/react-native-tracker/src/constants.ts create mode 100644 trackers/react-native-tracker/src/plugins/platform_context/index.ts create mode 100644 trackers/react-native-tracker/test/plugins/platform_context_android.test.ts create mode 100644 trackers/react-native-tracker/test/plugins/platform_context_ios.test.ts diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.md index 10f2ebe20..f983bfb46 100644 --- a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.md +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.md @@ -9,6 +9,7 @@ | Enumeration | Description | | --- | --- | | [LOG\_LEVEL](./react-native-tracker.log_level.md) | | +| [PlatformContextProperty](./react-native-tracker.platformcontextproperty.md) | | ## Functions @@ -39,6 +40,8 @@ | [Logger](./react-native-tracker.logger.md) | | | [PageViewEvent](./react-native-tracker.pageviewevent.md) | A Page View Event Represents a Page View, which is typically fired as soon as possible when a web page is loaded within the users browser. Often also fired on "virtual page views" within Single Page Applications (SPA). | | [PayloadBuilder](./react-native-tracker.payloadbuilder.md) | Interface for mutable object encapsulating tracker payload | +| [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) | | +| [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) | Overrides for the values for properties of the platform context. | | [RuleSet](./react-native-tracker.ruleset.md) | A ruleset has accept or reject properties that contain rules for matching Iglu schema URIs | | [SessionConfiguration](./react-native-tracker.sessionconfiguration.md) | Configuration for session tracking | | [StructuredEvent](./react-native-tracker.structuredevent.md) | A Structured Event A classic style of event tracking, allows for easier movement between analytics systems. A loosely typed event, creating a Self Describing event is preferred, but useful for interoperability. | diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.newtracker.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.newtracker.md index da09aff2a..23287faed 100644 --- a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.newtracker.md +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.newtracker.md @@ -9,14 +9,14 @@ Creates a new tracker instance with the given configuration Signature: ```typescript -export declare function newTracker(configuration: TrackerConfiguration & EmitterConfiguration & SessionConfiguration & SubjectConfiguration & EventStoreConfiguration): Promise; +export declare function newTracker(configuration: TrackerConfiguration & EmitterConfiguration & SessionConfiguration & SubjectConfiguration & EventStoreConfiguration & PlatformContextConfiguration): Promise; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| configuration | [TrackerConfiguration](./react-native-tracker.trackerconfiguration.md) & EmitterConfiguration & [SessionConfiguration](./react-native-tracker.sessionconfiguration.md) & [SubjectConfiguration](./react-native-tracker.subjectconfiguration.md) & [EventStoreConfiguration](./react-native-tracker.eventstoreconfiguration.md) | Configuration for the tracker | +| configuration | [TrackerConfiguration](./react-native-tracker.trackerconfiguration.md) & EmitterConfiguration & [SessionConfiguration](./react-native-tracker.sessionconfiguration.md) & [SubjectConfiguration](./react-native-tracker.subjectconfiguration.md) & [EventStoreConfiguration](./react-native-tracker.eventstoreconfiguration.md) & [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) | Configuration for the tracker | Returns: diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.md new file mode 100644 index 000000000..61b007e54 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) + +## PlatformContextConfiguration interface + +Signature: + +```typescript +export interface PlatformContextConfiguration +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [platformContext?](./react-native-tracker.platformcontextconfiguration.platformcontext.md) | boolean | (Optional) Whether to track the mobile context with information about the device. Note: Only some properties (osType, osVersion, deviceManufacturer, deviceModel, resolution, language, scale) will be tracked by default. Other properties can be assigned using the PlatformContextRetriever. | +| [platformContextProperties?](./react-native-tracker.platformcontextconfiguration.platformcontextproperties.md) | [PlatformContextProperty](./react-native-tracker.platformcontextproperty.md)\[\] | (Optional) List of properties of the platform context to track. If not passed and platformContext is enabled, all available properties will be tracked. The required osType, osVersion, deviceManufacturer, and deviceModel properties will be tracked in the entity regardless of this setting. | +| [platformContextRetriever?](./react-native-tracker.platformcontextconfiguration.platformcontextretriever.md) | [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) | (Optional) Set of callbacks to be used to retrieve properties of the platform context. Overrides the tracker implementation for setting the properties. | + diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontext.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontext.md new file mode 100644 index 000000000..a85e79fbf --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontext.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) > [platformContext](./react-native-tracker.platformcontextconfiguration.platformcontext.md) + +## PlatformContextConfiguration.platformContext property + +Whether to track the mobile context with information about the device. Note: Only some properties (osType, osVersion, deviceManufacturer, deviceModel, resolution, language, scale) will be tracked by default. Other properties can be assigned using the PlatformContextRetriever. + +Signature: + +```typescript +platformContext?: boolean; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextproperties.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextproperties.md new file mode 100644 index 000000000..da4fbf232 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextproperties.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) > [platformContextProperties](./react-native-tracker.platformcontextconfiguration.platformcontextproperties.md) + +## PlatformContextConfiguration.platformContextProperties property + +List of properties of the platform context to track. If not passed and `platformContext` is enabled, all available properties will be tracked. The required `osType`, `osVersion`, `deviceManufacturer`, and `deviceModel` properties will be tracked in the entity regardless of this setting. + +Signature: + +```typescript +platformContextProperties?: PlatformContextProperty[]; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextretriever.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextretriever.md new file mode 100644 index 000000000..b827c3a15 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextconfiguration.platformcontextretriever.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextConfiguration](./react-native-tracker.platformcontextconfiguration.md) > [platformContextRetriever](./react-native-tracker.platformcontextconfiguration.platformcontextretriever.md) + +## PlatformContextConfiguration.platformContextRetriever property + +Set of callbacks to be used to retrieve properties of the platform context. Overrides the tracker implementation for setting the properties. + +Signature: + +```typescript +platformContextRetriever?: PlatformContextRetriever; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextproperty.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextproperty.md new file mode 100644 index 000000000..ceefd9368 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextproperty.md @@ -0,0 +1,37 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextProperty](./react-native-tracker.platformcontextproperty.md) + +## PlatformContextProperty enum + +Signature: + +```typescript +export declare enum PlatformContextProperty +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| AndroidIdfa | "androidIdfa" | Advertising identifier on Android. Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| AppAvailableMemory | "appAvailableMemory" | Amount of memory in bytes available to the current app. The property is not tracked in the current version of the tracker due to the tracker not being able to access the API, see the issue here: https://github.com/snowplow/snowplow-ios-tracker/issues/772 Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| AppleIdfa | "appleIdfa" | Advertising identifier on iOS. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| AppleIdfv | "appleIdfv" | UUID identifier for vendors on iOS. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| AppSetId | "appSetId" | Android vendor ID scoped to the set of apps published under the same Google Play developer account (see https://developer.android.com/training/articles/app-set-id). Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| AppSetIdScope | "appSetIdScope" | Scope of the appSetId. Can be scoped to the app or to a developer account on an app store (all apps from the same developer on the same device will have the same ID). Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| AvailableStorage | "availableStorage" | Bytes of storage remaining. Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| BatteryLevel | "batteryLevel" | Remaining battery level as an integer percentage of total battery capacity. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| BatteryState | "batteryState" | Battery state for the device. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| Carrier | "carrier" | The carrier of the SIM inserted in the device. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| IsPortrait | "isPortrait" | A Boolean indicating whether the device orientation is portrait (either upright or upside down). Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| Language | "language" | System language currently used on the device (ISO 639). | +| LowPowerMode | "lowPowerMode" | A Boolean indicating whether Low Power Mode is enabled. | +| NetworkTechnology | "networkTechnology" | Radio access technology that the device is using. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| NetworkType | "networkType" | Type of network the device is connected to. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| PhysicalMemory | "physicalMemory" | Total physical system memory in bytes. Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. | +| Resolution | "resolution" | Screen resolution in pixels. Arrives in the form of WIDTHxHEIGHT (e.g., 1200x900). Doesn't change when device orientation changes. Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| Scale | "scale" | Scale factor used to convert logical coordinates to device coordinates of the screen (uses UIScreen.scale on iOS). | +| SystemAvailableMemory | "systemAvailableMemory" | Available memory on the system in bytes (Android only). Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | +| TotalStorage | "totalStorage" | Total size of storage in bytes. Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. | + diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getandroididfa.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getandroididfa.md new file mode 100644 index 000000000..d27e5b82d --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getandroididfa.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAndroidIdfa](./react-native-tracker.platformcontextretriever.getandroididfa.md) + +## PlatformContextRetriever.getAndroidIdfa property + +Advertising identifier on Android. + +Signature: + +```typescript +getAndroidIdfa?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappavailablememory.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappavailablememory.md new file mode 100644 index 000000000..624308467 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappavailablememory.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAppAvailableMemory](./react-native-tracker.platformcontextretriever.getappavailablememory.md) + +## PlatformContextRetriever.getAppAvailableMemory property + +Amount of memory in bytes available to the current app + +Signature: + +```typescript +getAppAvailableMemory?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfa.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfa.md new file mode 100644 index 000000000..a0d88db3b --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfa.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAppleIdfa](./react-native-tracker.platformcontextretriever.getappleidfa.md) + +## PlatformContextRetriever.getAppleIdfa property + +Advertising identifier on iOS (UUID formatted string) + +Signature: + +```typescript +getAppleIdfa?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfv.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfv.md new file mode 100644 index 000000000..368d90deb --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappleidfv.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAppleIdfv](./react-native-tracker.platformcontextretriever.getappleidfv.md) + +## PlatformContextRetriever.getAppleIdfv property + +UUID identifier for vendors on iOS + +Signature: + +```typescript +getAppleIdfv?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetid.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetid.md new file mode 100644 index 000000000..3c0658960 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetid.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAppSetId](./react-native-tracker.platformcontextretriever.getappsetid.md) + +## PlatformContextRetriever.getAppSetId property + +Android vendor ID scoped to the set of apps published under the same Google Play developer account (see https://developer.android.com/training/articles/app-set-id). + +Signature: + +```typescript +getAppSetId?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetidscope.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetidscope.md new file mode 100644 index 000000000..65b4c9854 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getappsetidscope.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAppSetIdScope](./react-native-tracker.platformcontextretriever.getappsetidscope.md) + +## PlatformContextRetriever.getAppSetIdScope property + +Scope of the `appSetId`. Can be scoped to the app or to a developer account on an app store (all apps from the same developer on the same device will have the same ID). + +Signature: + +```typescript +getAppSetIdScope?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getavailablestorage.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getavailablestorage.md new file mode 100644 index 000000000..ce013083a --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getavailablestorage.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getAvailableStorage](./react-native-tracker.platformcontextretriever.getavailablestorage.md) + +## PlatformContextRetriever.getAvailableStorage property + +Bytes of storage remaining + +Signature: + +```typescript +getAvailableStorage?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterylevel.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterylevel.md new file mode 100644 index 000000000..a08a446e6 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterylevel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getBatteryLevel](./react-native-tracker.platformcontextretriever.getbatterylevel.md) + +## PlatformContextRetriever.getBatteryLevel property + +Remaining battery level as an integer percentage of total battery capacity + +Signature: + +```typescript +getBatteryLevel?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterystate.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterystate.md new file mode 100644 index 000000000..ca43c26d9 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getbatterystate.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getBatteryState](./react-native-tracker.platformcontextretriever.getbatterystate.md) + +## PlatformContextRetriever.getBatteryState property + +Battery state for the device + +Signature: + +```typescript +getBatteryState?: () => Promise<'unplugged' | 'charging' | 'full' | undefined>; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getcarrier.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getcarrier.md new file mode 100644 index 000000000..f1515b6e3 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getcarrier.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getCarrier](./react-native-tracker.platformcontextretriever.getcarrier.md) + +## PlatformContextRetriever.getCarrier property + +The carrier of the SIM inserted in the device + +Signature: + +```typescript +getCarrier?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemanufacturer.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemanufacturer.md new file mode 100644 index 000000000..aefca54ec --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemanufacturer.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getDeviceManufacturer](./react-native-tracker.platformcontextretriever.getdevicemanufacturer.md) + +## PlatformContextRetriever.getDeviceManufacturer property + +The manufacturer of the product/hardware + +Signature: + +```typescript +getDeviceManufacturer?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemodel.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemodel.md new file mode 100644 index 000000000..c6c5f4fac --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getdevicemodel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getDeviceModel](./react-native-tracker.platformcontextretriever.getdevicemodel.md) + +## PlatformContextRetriever.getDeviceModel property + +The end-user-visible name for the end product + +Signature: + +```typescript +getDeviceModel?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlanguage.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlanguage.md new file mode 100644 index 000000000..565a371b8 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlanguage.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getLanguage](./react-native-tracker.platformcontextretriever.getlanguage.md) + +## PlatformContextRetriever.getLanguage property + +System language currently used on the device (ISO 639) + +Signature: + +```typescript +getLanguage?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlowpowermode.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlowpowermode.md new file mode 100644 index 000000000..368092360 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getlowpowermode.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getLowPowerMode](./react-native-tracker.platformcontextretriever.getlowpowermode.md) + +## PlatformContextRetriever.getLowPowerMode property + +A Boolean indicating whether Low Power Mode is enabled + +Signature: + +```typescript +getLowPowerMode?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktechnology.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktechnology.md new file mode 100644 index 000000000..8302c9a24 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktechnology.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getNetworkTechnology](./react-native-tracker.platformcontextretriever.getnetworktechnology.md) + +## PlatformContextRetriever.getNetworkTechnology property + +Radio access technology that the device is using + +Signature: + +```typescript +getNetworkTechnology?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktype.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktype.md new file mode 100644 index 000000000..0b00accd9 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getnetworktype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getNetworkType](./react-native-tracker.platformcontextretriever.getnetworktype.md) + +## PlatformContextRetriever.getNetworkType property + +Type of network the device is connected to + +Signature: + +```typescript +getNetworkType?: () => Promise<'mobile' | 'wifi' | 'offline' | undefined>; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getostype.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getostype.md new file mode 100644 index 000000000..456b4aad5 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getostype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getOsType](./react-native-tracker.platformcontextretriever.getostype.md) + +## PlatformContextRetriever.getOsType property + +Operating system type (e.g., ios, tvos, watchos, osx, android) + +Signature: + +```typescript +getOsType?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getosversion.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getosversion.md new file mode 100644 index 000000000..b46d441dc --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getosversion.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getOsVersion](./react-native-tracker.platformcontextretriever.getosversion.md) + +## PlatformContextRetriever.getOsVersion property + +The current version of the operating system + +Signature: + +```typescript +getOsVersion?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getphysicalmemory.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getphysicalmemory.md new file mode 100644 index 000000000..16900d371 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getphysicalmemory.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getPhysicalMemory](./react-native-tracker.platformcontextretriever.getphysicalmemory.md) + +## PlatformContextRetriever.getPhysicalMemory property + +Total physical system memory in bytes + +Signature: + +```typescript +getPhysicalMemory?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getresolution.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getresolution.md new file mode 100644 index 000000000..38f1da167 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getresolution.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getResolution](./react-native-tracker.platformcontextretriever.getresolution.md) + +## PlatformContextRetriever.getResolution property + +Screen resolution in pixels. Arrives in the form of WIDTHxHEIGHT (e.g., 1200x900). Doesn't change when device orientation changes + +Signature: + +```typescript +getResolution?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getscale.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getscale.md new file mode 100644 index 000000000..4ea6d0605 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getscale.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getScale](./react-native-tracker.platformcontextretriever.getscale.md) + +## PlatformContextRetriever.getScale property + +Scale factor used to convert logical coordinates to device coordinates of the screen (uses UIScreen.scale on iOS) + +Signature: + +```typescript +getScale?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getsystemavailablememory.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getsystemavailablememory.md new file mode 100644 index 000000000..a172c17f7 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.getsystemavailablememory.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getSystemAvailableMemory](./react-native-tracker.platformcontextretriever.getsystemavailablememory.md) + +## PlatformContextRetriever.getSystemAvailableMemory property + +Available memory on the system in bytes (Android only). + +Signature: + +```typescript +getSystemAvailableMemory?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.gettotalstorage.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.gettotalstorage.md new file mode 100644 index 000000000..608b4a868 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.gettotalstorage.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [getTotalStorage](./react-native-tracker.platformcontextretriever.gettotalstorage.md) + +## PlatformContextRetriever.getTotalStorage property + +Total size of storage in bytes + +Signature: + +```typescript +getTotalStorage?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.isportrait.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.isportrait.md new file mode 100644 index 000000000..4e633ff9b --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.isportrait.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) > [isPortrait](./react-native-tracker.platformcontextretriever.isportrait.md) + +## PlatformContextRetriever.isPortrait property + +A Boolean indicating whether the device orientation is portrait (either upright or upside down) + +Signature: + +```typescript +isPortrait?: () => Promise; +``` diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.md new file mode 100644 index 000000000..a93833f88 --- /dev/null +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.platformcontextretriever.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [@snowplow/react-native-tracker](./react-native-tracker.md) > [PlatformContextRetriever](./react-native-tracker.platformcontextretriever.md) + +## PlatformContextRetriever interface + +Overrides for the values for properties of the platform context. + +Signature: + +```typescript +export interface PlatformContextRetriever +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getAndroidIdfa?](./react-native-tracker.platformcontextretriever.getandroididfa.md) | () => Promise<string \| undefined> | (Optional) Advertising identifier on Android. | +| [getAppAvailableMemory?](./react-native-tracker.platformcontextretriever.getappavailablememory.md) | () => Promise<number \| undefined> | (Optional) Amount of memory in bytes available to the current app | +| [getAppleIdfa?](./react-native-tracker.platformcontextretriever.getappleidfa.md) | () => Promise<string \| undefined> | (Optional) Advertising identifier on iOS (UUID formatted string) | +| [getAppleIdfv?](./react-native-tracker.platformcontextretriever.getappleidfv.md) | () => Promise<string \| undefined> | (Optional) UUID identifier for vendors on iOS | +| [getAppSetId?](./react-native-tracker.platformcontextretriever.getappsetid.md) | () => Promise<string \| undefined> | (Optional) Android vendor ID scoped to the set of apps published under the same Google Play developer account (see https://developer.android.com/training/articles/app-set-id). | +| [getAppSetIdScope?](./react-native-tracker.platformcontextretriever.getappsetidscope.md) | () => Promise<string \| undefined> | (Optional) Scope of the appSetId. Can be scoped to the app or to a developer account on an app store (all apps from the same developer on the same device will have the same ID). | +| [getAvailableStorage?](./react-native-tracker.platformcontextretriever.getavailablestorage.md) | () => Promise<number \| undefined> | (Optional) Bytes of storage remaining | +| [getBatteryLevel?](./react-native-tracker.platformcontextretriever.getbatterylevel.md) | () => Promise<number \| undefined> | (Optional) Remaining battery level as an integer percentage of total battery capacity | +| [getBatteryState?](./react-native-tracker.platformcontextretriever.getbatterystate.md) | () => Promise<'unplugged' \| 'charging' \| 'full' \| undefined> | (Optional) Battery state for the device | +| [getCarrier?](./react-native-tracker.platformcontextretriever.getcarrier.md) | () => Promise<string \| undefined> | (Optional) The carrier of the SIM inserted in the device | +| [getDeviceManufacturer?](./react-native-tracker.platformcontextretriever.getdevicemanufacturer.md) | () => Promise<string> | (Optional) The manufacturer of the product/hardware | +| [getDeviceModel?](./react-native-tracker.platformcontextretriever.getdevicemodel.md) | () => Promise<string> | (Optional) The end-user-visible name for the end product | +| [getLanguage?](./react-native-tracker.platformcontextretriever.getlanguage.md) | () => Promise<string \| undefined> | (Optional) System language currently used on the device (ISO 639) | +| [getLowPowerMode?](./react-native-tracker.platformcontextretriever.getlowpowermode.md) | () => Promise<boolean \| undefined> | (Optional) A Boolean indicating whether Low Power Mode is enabled | +| [getNetworkTechnology?](./react-native-tracker.platformcontextretriever.getnetworktechnology.md) | () => Promise<string \| undefined> | (Optional) Radio access technology that the device is using | +| [getNetworkType?](./react-native-tracker.platformcontextretriever.getnetworktype.md) | () => Promise<'mobile' \| 'wifi' \| 'offline' \| undefined> | (Optional) Type of network the device is connected to | +| [getOsType?](./react-native-tracker.platformcontextretriever.getostype.md) | () => Promise<string> | (Optional) Operating system type (e.g., ios, tvos, watchos, osx, android) | +| [getOsVersion?](./react-native-tracker.platformcontextretriever.getosversion.md) | () => Promise<string> | (Optional) The current version of the operating system | +| [getPhysicalMemory?](./react-native-tracker.platformcontextretriever.getphysicalmemory.md) | () => Promise<number \| undefined> | (Optional) Total physical system memory in bytes | +| [getResolution?](./react-native-tracker.platformcontextretriever.getresolution.md) | () => Promise<string \| undefined> | (Optional) Screen resolution in pixels. Arrives in the form of WIDTHxHEIGHT (e.g., 1200x900). Doesn't change when device orientation changes | +| [getScale?](./react-native-tracker.platformcontextretriever.getscale.md) | () => Promise<number \| undefined> | (Optional) Scale factor used to convert logical coordinates to device coordinates of the screen (uses UIScreen.scale on iOS) | +| [getSystemAvailableMemory?](./react-native-tracker.platformcontextretriever.getsystemavailablememory.md) | () => Promise<number \| undefined> | (Optional) Available memory on the system in bytes (Android only). | +| [getTotalStorage?](./react-native-tracker.platformcontextretriever.gettotalstorage.md) | () => Promise<number \| undefined> | (Optional) Total size of storage in bytes | +| [isPortrait?](./react-native-tracker.platformcontextretriever.isportrait.md) | () => Promise<boolean \| undefined> | (Optional) A Boolean indicating whether the device orientation is portrait (either upright or upside down) | + diff --git a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.reactnativetracker.md b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.reactnativetracker.md index 00f678ae0..62187fe7b 100644 --- a/api-docs/docs/react-native-tracker/markdown/react-native-tracker.reactnativetracker.md +++ b/api-docs/docs/react-native-tracker/markdown/react-native-tracker.reactnativetracker.md @@ -33,6 +33,9 @@ export declare type ReactNativeTracker = { readonly setScreenViewport: (newView: ScreenSize) => void; readonly setColorDepth: (newLang: number) => void; readonly setSubjectData: (config: SubjectConfiguration) => void; + readonly enablePlatformContext: () => Promise; + readonly disablePlatformContext: () => void; + readonly refreshPlatformContext: () => Promise; }; ``` References: [EventContext](./react-native-tracker.eventcontext.md), [TimingProps](./react-native-tracker.timingprops.md), [MessageNotificationProps](./react-native-tracker.messagenotificationprops.md), [ScreenSize](./react-native-tracker.screensize.md), [SubjectConfiguration](./react-native-tracker.subjectconfiguration.md) diff --git a/api-docs/docs/react-native-tracker/react-native-tracker.api.md b/api-docs/docs/react-native-tracker/react-native-tracker.api.md index a48e04ddf..b699df1c6 100644 --- a/api-docs/docs/react-native-tracker/react-native-tracker.api.md +++ b/api-docs/docs/react-native-tracker/react-native-tracker.api.md @@ -251,7 +251,7 @@ export type MessageNotificationProps = { }; // @public -export function newTracker(configuration: TrackerConfiguration & EmitterConfiguration & SessionConfiguration & SubjectConfiguration & EventStoreConfiguration): Promise; +export function newTracker(configuration: TrackerConfiguration & EmitterConfiguration & SessionConfiguration & SubjectConfiguration & EventStoreConfiguration & PlatformContextConfiguration): Promise; // @public export interface PageViewEvent { @@ -275,6 +275,65 @@ export interface PayloadBuilder { withJsonProcessor: (jsonProcessor: JsonProcessor) => void; } +// @public (undocumented) +export interface PlatformContextConfiguration { + platformContext?: boolean; + platformContextProperties?: PlatformContextProperty[]; + platformContextRetriever?: PlatformContextRetriever; +} + +// @public (undocumented) +export enum PlatformContextProperty { + AndroidIdfa = "androidIdfa", + AppAvailableMemory = "appAvailableMemory", + AppleIdfa = "appleIdfa", + AppleIdfv = "appleIdfv", + AppSetId = "appSetId", + AppSetIdScope = "appSetIdScope", + AvailableStorage = "availableStorage", + BatteryLevel = "batteryLevel", + BatteryState = "batteryState", + Carrier = "carrier", + IsPortrait = "isPortrait", + Language = "language", + LowPowerMode = "lowPowerMode", + NetworkTechnology = "networkTechnology", + NetworkType = "networkType", + PhysicalMemory = "physicalMemory", + Resolution = "resolution", + Scale = "scale", + SystemAvailableMemory = "systemAvailableMemory", + TotalStorage = "totalStorage" +} + +// @public +export interface PlatformContextRetriever { + getAndroidIdfa?: () => Promise; + getAppAvailableMemory?: () => Promise; + getAppleIdfa?: () => Promise; + getAppleIdfv?: () => Promise; + getAppSetId?: () => Promise; + getAppSetIdScope?: () => Promise; + getAvailableStorage?: () => Promise; + getBatteryLevel?: () => Promise; + getBatteryState?: () => Promise<'unplugged' | 'charging' | 'full' | undefined>; + getCarrier?: () => Promise; + getDeviceManufacturer?: () => Promise; + getDeviceModel?: () => Promise; + getLanguage?: () => Promise; + getLowPowerMode?: () => Promise; + getNetworkTechnology?: () => Promise; + getNetworkType?: () => Promise<'mobile' | 'wifi' | 'offline' | undefined>; + getOsType?: () => Promise; + getOsVersion?: () => Promise; + getPhysicalMemory?: () => Promise; + getResolution?: () => Promise; + getScale?: () => Promise; + getSystemAvailableMemory?: () => Promise; + getTotalStorage?: () => Promise; + isPortrait?: () => Promise; +} + // @public export type ReactNativeTracker = { readonly trackSelfDescribingEvent: = Record>(argmap: SelfDescribingJson, contexts?: EventContext[]) => void; @@ -300,6 +359,9 @@ export type ReactNativeTracker = { readonly setScreenViewport: (newView: ScreenSize) => void; readonly setColorDepth: (newLang: number) => void; readonly setSubjectData: (config: SubjectConfiguration) => void; + readonly enablePlatformContext: () => Promise; + readonly disablePlatformContext: () => void; + readonly refreshPlatformContext: () => Promise; }; // @public diff --git a/trackers/react-native-tracker/src/constants.ts b/trackers/react-native-tracker/src/constants.ts new file mode 100644 index 000000000..b813c85f8 --- /dev/null +++ b/trackers/react-native-tracker/src/constants.ts @@ -0,0 +1 @@ +export const MOBILE_CONTEXT_SCHEMA = 'iglu:com.snowplowanalytics.snowplow/mobile_context/jsonschema/1-0-3'; diff --git a/trackers/react-native-tracker/src/plugins/platform_context/index.ts b/trackers/react-native-tracker/src/plugins/platform_context/index.ts new file mode 100644 index 000000000..477b57102 --- /dev/null +++ b/trackers/react-native-tracker/src/plugins/platform_context/index.ts @@ -0,0 +1,327 @@ +import { CorePluginConfiguration } from '@snowplow/tracker-core'; +import { PlatformContextConfiguration, PlatformContextProperty } from '../../types'; +import { MOBILE_CONTEXT_SCHEMA } from '../../constants'; +import { Platform, PlatformIOSStatic, PlatformConstants, Dimensions, PixelRatio, NativeModules } from 'react-native'; +import { removeEmptyProperties } from '@snowplow/tracker-core'; + +export interface PlatformContextPlugin extends CorePluginConfiguration { + enablePlatformContext: () => Promise; + disablePlatformContext: () => void; + refreshPlatformContext: () => Promise; +} + + +function getIOSConstants() { + // Example Platform info on iOS: + // { + // "OS": "ios", + // "Version": "18.0", + // "constants": { + // "forceTouchAvailable": false, + // "interfaceIdiom": "phone", + // "isMacCatalyst": false, + // "isTesting": false, + // "osVersion": "18.0", + // "systemName": "iOS" + // }, + // "isMacCatalyst": false, + // "isPad": false, + // "isTV": false, + // "isVision": false + // } + + // Example NativeModules.SettingsManager?.settings info on iOS: + // { + // "AppleLanguages": [ + // "en-GB" + // ], + // "AppleLocale": "en_GB" + // } + + const constants = Platform.constants as PlatformConstants & { + osVersion: string; + systemName: string; + isMacCatalyst?: boolean | undefined; + }; + return { + osType: constants.systemName, + deviceManufacturer: 'Apple', + osVersion: constants.osVersion, + deviceModel: (Platform as PlatformIOSStatic).isPad + ? 'iPad' + : Platform.isTV + ? 'Apple TV' + : (Platform as PlatformIOSStatic).isVision + ? 'Vision' + : (Platform as PlatformIOSStatic).isMacCatalyst + ? 'Mac' + : 'iPhone', + language: + NativeModules.SettingsManager?.settings?.AppleLocale || + NativeModules.SettingsManager?.settings?.AppleLanguages[0], //iOS 13 + }; +} + +function getAndroidConstants() { + // Example Platform info on Android: + // { + // "OS": "android", + // "Version": 33, + // "constants": { + // "Brand": "google", + // "Manufacturer": "Google", + // "Model": "sdk_gphone64_arm64", + // "Release": "13", + // "Version": 33, + // }, + // } + + // Example NativeModules.I18nManager info on Android: + // { "localeIdentifier": "en_US" } + const constants = Platform.constants as PlatformConstants & { + Version: number; + Model: string; + Manufacturer: string; + }; + return { + osType: 'Android', + deviceManufacturer: constants.Manufacturer, + osVersion: String(constants.Version), + deviceModel: constants.Model, + language: NativeModules.I18nManager?.localeIdentifier, + }; +} + +/** + * Tracks a mobile_context entity with all events if platformContext is enabled. + */ +export async function newPlatformContextPlugin({ + platformContext = true, + platformContextProperties, + platformContextRetriever, +}: PlatformContextConfiguration = {}): Promise { + let deviceModel: string | undefined; + let osType: string | undefined; + let deviceManufacturer: string | undefined; + let osVersion: string | undefined; + let carrier: string | undefined; + let networkType: 'mobile' | 'wifi' | 'offline' | undefined; + let networkTechnology: string | undefined; + let appleIdfa: string | undefined; + let appleIdfv: string | undefined; + let androidIdfa: string | undefined; + let physicalMemory: number | undefined; + let systemAvailableMemory: number | undefined; + let appAvailableMemory: number | undefined; + let batteryLevel: number | undefined; + let batteryState: 'unplugged' | 'charging' | 'full' | undefined; + let lowPowerMode: boolean | undefined; + let availableStorage: number | undefined; + let totalStorage: number | undefined; + let isPortrait: boolean | undefined; + let resolution: string | undefined; + let scale: number | undefined; + let language: string | undefined; + let appSetId: string | undefined; + let appSetIdScope: string | undefined; + + const refreshPlatformContext = async () => { + const constants = + Platform.OS === 'ios' ? getIOSConstants() : Platform.OS == 'android' ? getAndroidConstants() : undefined; + + deviceModel = platformContextRetriever?.getDeviceModel + ? await platformContextRetriever?.getDeviceModel() + : constants?.deviceModel; + osType = platformContextRetriever?.getOsType ? await platformContextRetriever?.getOsType() : constants?.osType; + deviceManufacturer = platformContextRetriever?.getDeviceManufacturer + ? await platformContextRetriever?.getDeviceManufacturer() + : constants?.deviceManufacturer; + osVersion = platformContextRetriever?.getOsVersion + ? await platformContextRetriever?.getOsVersion() + : constants?.osVersion; + carrier = + platformContextProperties?.includes(PlatformContextProperty.Carrier) ?? true + ? platformContextRetriever?.getCarrier + ? await platformContextRetriever?.getCarrier() + : undefined + : undefined; + networkType = + platformContextProperties?.includes(PlatformContextProperty.NetworkType) ?? true + ? platformContextRetriever?.getNetworkType + ? await platformContextRetriever?.getNetworkType() + : undefined + : undefined; + networkTechnology = platformContextRetriever?.getNetworkTechnology + ? await platformContextRetriever?.getNetworkTechnology() + : undefined; + appleIdfa = + platformContextProperties?.includes(PlatformContextProperty.AppleIdfa) ?? true + ? platformContextRetriever?.getAppleIdfa + ? await platformContextRetriever?.getAppleIdfa() + : undefined + : undefined; + appleIdfv = + platformContextProperties?.includes(PlatformContextProperty.AppleIdfv) ?? true + ? platformContextRetriever?.getAppleIdfv + ? await platformContextRetriever?.getAppleIdfv() + : undefined + : undefined; + androidIdfa = + platformContextProperties?.includes(PlatformContextProperty.AndroidIdfa) ?? true + ? platformContextRetriever?.getAndroidIdfa + ? await platformContextRetriever?.getAndroidIdfa() + : undefined + : undefined; + physicalMemory = + platformContextProperties?.includes(PlatformContextProperty.PhysicalMemory) ?? true + ? platformContextRetriever?.getPhysicalMemory + ? await platformContextRetriever.getPhysicalMemory() + : undefined + : undefined; + systemAvailableMemory = + platformContextProperties?.includes(PlatformContextProperty.SystemAvailableMemory) ?? true + ? platformContextRetriever?.getSystemAvailableMemory + ? await platformContextRetriever.getSystemAvailableMemory() + : undefined + : undefined; + appAvailableMemory = + platformContextProperties?.includes(PlatformContextProperty.AppAvailableMemory) ?? true + ? platformContextRetriever?.getAppAvailableMemory + ? await platformContextRetriever?.getAppAvailableMemory() + : undefined + : undefined; + batteryLevel = + platformContextProperties?.includes(PlatformContextProperty.BatteryLevel) ?? true + ? platformContextRetriever?.getBatteryLevel + ? await platformContextRetriever?.getBatteryLevel() + : undefined + : undefined; + batteryState = + platformContextProperties?.includes(PlatformContextProperty.BatteryState) ?? true + ? platformContextRetriever?.getBatteryState + ? await platformContextRetriever?.getBatteryState() + : undefined + : undefined; + lowPowerMode = + platformContextProperties?.includes(PlatformContextProperty.LowPowerMode) ?? true + ? platformContextRetriever?.getLowPowerMode + ? await platformContextRetriever?.getLowPowerMode() + : undefined + : undefined; + availableStorage = + platformContextProperties?.includes(PlatformContextProperty.AvailableStorage) ?? true + ? platformContextRetriever?.getAvailableStorage + ? await platformContextRetriever?.getAvailableStorage() + : undefined + : undefined; + totalStorage = + platformContextProperties?.includes(PlatformContextProperty.TotalStorage) ?? true + ? platformContextRetriever?.getTotalStorage + ? await platformContextRetriever?.getTotalStorage() + : undefined + : undefined; + isPortrait = + platformContextProperties?.includes(PlatformContextProperty.IsPortrait) ?? true + ? platformContextRetriever?.isPortrait + ? await platformContextRetriever.isPortrait() + : undefined + : undefined; + resolution = + platformContextProperties?.includes(PlatformContextProperty.Resolution) ?? true + ? platformContextRetriever?.getResolution + ? await platformContextRetriever?.getResolution() + : Dimensions.get('window').width + 'x' + Dimensions.get('window').height + : undefined; + scale = + platformContextProperties?.includes(PlatformContextProperty.Scale) ?? true + ? platformContextRetriever?.getScale + ? await platformContextRetriever?.getScale() + : PixelRatio.get() + : undefined; + language = + platformContextProperties?.includes(PlatformContextProperty.Language) ?? true + ? platformContextRetriever?.getLanguage + ? await platformContextRetriever?.getLanguage() + : constants?.language + : undefined; + appSetId = + platformContextProperties?.includes(PlatformContextProperty.AppSetId) ?? true + ? platformContextRetriever?.getAppSetId + ? await platformContextRetriever?.getAppSetId() + : undefined + : undefined; + appSetIdScope = + platformContextProperties?.includes(PlatformContextProperty.AppSetIdScope) ?? true + ? platformContextRetriever?.getAppSetIdScope + ? await platformContextRetriever?.getAppSetIdScope() + : undefined + : undefined; + }; + + const enablePlatformContext = async () => { + platformContext = true; + await refreshPlatformContext(); + }; + + const disablePlatformContext = () => { + platformContext = false; + }; + + if (platformContext) { + await refreshPlatformContext(); + } + + const contexts = () => { + // check required properties + if ( + platformContext && + osType !== undefined && + osVersion !== undefined && + deviceManufacturer !== undefined && + deviceModel !== undefined + ) { + return [ + { + schema: MOBILE_CONTEXT_SCHEMA, + data: removeEmptyProperties({ + osType, + osVersion, + deviceManufacturer, + deviceModel, + carrier, + networkType, + networkTechnology, + appleIdfa, + appleIdfv, + androidIdfa, + physicalMemory, + systemAvailableMemory, + appAvailableMemory, + batteryLevel, + batteryState, + lowPowerMode, + availableStorage, + totalStorage, + isPortrait, + resolution, + scale, + language, + appSetId, + appSetIdScope, + }), + }, + ]; + } else { + return []; + } + }; + + return { + enablePlatformContext, + disablePlatformContext, + refreshPlatformContext, + plugin: { + contexts, + }, + }; +} diff --git a/trackers/react-native-tracker/src/tracker.ts b/trackers/react-native-tracker/src/tracker.ts index fca43fc5c..ccf6ef1f4 100644 --- a/trackers/react-native-tracker/src/tracker.ts +++ b/trackers/react-native-tracker/src/tracker.ts @@ -7,11 +7,13 @@ import { newSubject } from './subject'; import { EventStoreConfiguration, + PlatformContextConfiguration, ReactNativeTracker, SessionConfiguration, SubjectConfiguration, TrackerConfiguration, } from './types'; +import { newPlatformContextPlugin } from './plugins/platform_context'; const initializedTrackers: Record = {}; @@ -25,7 +27,8 @@ export async function newTracker( EmitterConfiguration & SessionConfiguration & SubjectConfiguration & - EventStoreConfiguration + EventStoreConfiguration & + PlatformContextConfiguration ): Promise { const { namespace, appId, encodeBase64 = false } = configuration; if (configuration.eventStore === undefined) { @@ -40,6 +43,9 @@ export async function newTracker( const subject = newSubject(core, configuration); core.addPlugin(subject.subjectPlugin); + const platformContextPlugin = await newPlatformContextPlugin(configuration); + core.addPlugin(platformContextPlugin); + core.setPlatform('mob'); // default platform core.setTrackerVersion('rn-' + version); core.setTrackerNamespace(namespace); @@ -56,6 +62,9 @@ export async function newTracker( addGlobalContexts: core.addGlobalContexts, removeGlobalContexts: core.removeGlobalContexts, clearGlobalContexts: core.clearGlobalContexts, + enablePlatformContext: platformContextPlugin.enablePlatformContext, + disablePlatformContext: platformContextPlugin.disablePlatformContext, + refreshPlatformContext: platformContextPlugin.refreshPlatformContext, addPlugin: core.addPlugin, }; initializedTrackers[namespace] = { tracker, core }; diff --git a/trackers/react-native-tracker/src/types.ts b/trackers/react-native-tracker/src/types.ts index a7d31fade..2183bf679 100755 --- a/trackers/react-native-tracker/src/types.ts +++ b/trackers/react-native-tracker/src/types.ts @@ -57,6 +57,203 @@ export interface TrackerConfiguration { encodeBase64?: boolean; } +export enum PlatformContextProperty { + /** + * The carrier of the SIM inserted in the device. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + Carrier = 'carrier', + /** + * Type of network the device is connected to. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + NetworkType = 'networkType', + /** + * Radio access technology that the device is using. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + NetworkTechnology = 'networkTechnology', + /** + * Advertising identifier on iOS. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + AppleIdfa = 'appleIdfa', + /** + * UUID identifier for vendors on iOS. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + AppleIdfv = 'appleIdfv', + /** + * Total physical system memory in bytes. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + PhysicalMemory = 'physicalMemory', + /** + * Amount of memory in bytes available to the current app. + * The property is not tracked in the current version of the tracker due to the tracker not being able to access the API, see the issue here: https://github.com/snowplow/snowplow-ios-tracker/issues/772 + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + AppAvailableMemory = 'appAvailableMemory', + /** + * Remaining battery level as an integer percentage of total battery capacity. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + BatteryLevel = 'batteryLevel', + /** + * Battery state for the device. + * Note: this property is not automatically assigned but can be assigned using the PlatformContextRetriever. + */ + BatteryState = 'batteryState', + /** A Boolean indicating whether Low Power Mode is enabled. */ + LowPowerMode = 'lowPowerMode', + /** + * Bytes of storage remaining. + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + AvailableStorage = 'availableStorage', + /** + * Total size of storage in bytes. + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + TotalStorage = 'totalStorage', + /** + * A Boolean indicating whether the device orientation is portrait (either upright or upside down). + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + IsPortrait = 'isPortrait', + /** + * Screen resolution in pixels. Arrives in the form of WIDTHxHEIGHT (e.g., 1200x900). Doesn't change when device orientation changes. + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + Resolution = 'resolution', + /** + * Scale factor used to convert logical coordinates to device coordinates of the screen (uses UIScreen.scale on iOS). + */ + Scale = 'scale', + /** + * System language currently used on the device (ISO 639). + */ + Language = 'language', + /** + * Advertising identifier on Android. + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + AndroidIdfa = 'androidIdfa', + /** + * Available memory on the system in bytes (Android only). + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + SystemAvailableMemory = 'systemAvailableMemory', + /** + * Android vendor ID scoped to the set of apps published under the same Google Play developer account (see https://developer.android.com/training/articles/app-set-id). + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + AppSetId = 'appSetId', + /** + * Scope of the `appSetId`. Can be scoped to the app or to a developer account on an app store (all apps from the same developer on the same device will have the same ID). + * Note: This is not automatically assigned by the tracker as it may be considered as fingerprinting. You can assign it using the PlatformContextRetriever. + */ + AppSetIdScope = 'appSetIdScope', +} + +/** + * Overrides for the values for properties of the platform context. + */ +export interface PlatformContextRetriever { + /** Operating system type (e.g., ios, tvos, watchos, osx, android) */ + getOsType?: () => Promise; + + /** The current version of the operating system */ + getOsVersion?: () => Promise; + + /** The end-user-visible name for the end product */ + getDeviceModel?: () => Promise; + + /** The manufacturer of the product/hardware */ + getDeviceManufacturer?: () => Promise; + + /** The carrier of the SIM inserted in the device */ + getCarrier?: () => Promise; + + /** Type of network the device is connected to */ + getNetworkType?: () => Promise<'mobile' | 'wifi' | 'offline' | undefined>; + + /** Radio access technology that the device is using */ + getNetworkTechnology?: () => Promise; + + /** Advertising identifier on iOS (UUID formatted string) */ + getAppleIdfa?: () => Promise; + + /** UUID identifier for vendors on iOS */ + getAppleIdfv?: () => Promise; + + /** Bytes of storage remaining */ + getAvailableStorage?: () => Promise; + + /** Total size of storage in bytes */ + getTotalStorage?: () => Promise; + + /** Total physical system memory in bytes */ + getPhysicalMemory?: () => Promise; + + /** Amount of memory in bytes available to the current app */ + getAppAvailableMemory?: () => Promise; + + /** Remaining battery level as an integer percentage of total battery capacity */ + getBatteryLevel?: () => Promise; + + /** Battery state for the device */ + getBatteryState?: () => Promise<'unplugged' | 'charging' | 'full' | undefined>; + + /** A Boolean indicating whether Low Power Mode is enabled */ + getLowPowerMode?: () => Promise; + + /** A Boolean indicating whether the device orientation is portrait (either upright or upside down) */ + isPortrait?: () => Promise; + + /** Screen resolution in pixels. Arrives in the form of WIDTHxHEIGHT (e.g., 1200x900). Doesn't change when device orientation changes */ + getResolution?: () => Promise; + + /** Scale factor used to convert logical coordinates to device coordinates of the screen (uses UIScreen.scale on iOS) */ + getScale?: () => Promise; + + /** System language currently used on the device (ISO 639) */ + getLanguage?: () => Promise; + + /** Advertising identifier on Android. */ + getAndroidIdfa?: () => Promise; + + /** Available memory on the system in bytes (Android only). */ + getSystemAvailableMemory?: () => Promise; + + /** Android vendor ID scoped to the set of apps published under the same Google Play developer account (see https://developer.android.com/training/articles/app-set-id). */ + getAppSetId?: () => Promise; + + /** Scope of the `appSetId`. Can be scoped to the app or to a developer account on an app store (all apps from the same developer on the same device will have the same ID). */ + getAppSetIdScope?: () => Promise; +} + +export interface PlatformContextConfiguration { + /** + * Whether to track the mobile context with information about the device. + * Note: Only some properties (osType, osVersion, deviceManufacturer, deviceModel, resolution, language, scale) will be tracked by default. Other properties can be assigned using the PlatformContextRetriever. + * @defaultValue true + */ + platformContext?: boolean; + + /** + * List of properties of the platform context to track. If not passed and `platformContext` is enabled, all available properties will be tracked. + * The required `osType`, `osVersion`, `deviceManufacturer`, and `deviceModel` properties will be tracked in the entity regardless of this setting. + */ + platformContextProperties?: PlatformContextProperty[]; + + /** + * Set of callbacks to be used to retrieve properties of the platform context. + * Overrides the tracker implementation for setting the properties. + */ + platformContextRetriever?: PlatformContextRetriever; +} + /** * Configuration of subject properties tracked with events */ @@ -589,6 +786,22 @@ export type ReactNativeTracker = { // * @returns {Promise} // */ // readonly getForegroundIndex: () => Promise; + + /** + * Enables tracking the platform context with information about the device. + * Note: Only some properties (osType, osVersion, deviceManufacturer, deviceModel, resolution, language, scale) will be tracked by default. Other properties can be assigned using the PlatformContextRetriever. + */ + readonly enablePlatformContext: () => Promise; + + /** + * Disables tracking the platform context with information about the device. + */ + readonly disablePlatformContext: () => void; + + /** + * Refreshes the platform context with the latest values. + */ + readonly refreshPlatformContext: () => Promise; }; export { diff --git a/trackers/react-native-tracker/test/plugins/platform_context_android.test.ts b/trackers/react-native-tracker/test/plugins/platform_context_android.test.ts new file mode 100644 index 000000000..50dfd6072 --- /dev/null +++ b/trackers/react-native-tracker/test/plugins/platform_context_android.test.ts @@ -0,0 +1,50 @@ +import { buildPageView, Payload, trackerCore } from '@snowplow/tracker-core'; +import { newPlatformContextPlugin } from '../../src/plugins/platform_context'; +import { MOBILE_CONTEXT_SCHEMA } from '../../src/constants'; +import { NativeModules } from 'react-native'; + +describe('PlatformContextPlugin on Android', () => { + beforeAll(() => { + jest.mock('react-native/Libraries/Utilities/Platform', () => ({ + OS: 'android', + Version: 33, + constants: { + Brand: 'google', + Manufacturer: 'Google', + Model: 'sdk_gphone64_arm64', + Release: '13', + Version: 33, + }, + select: () => null, + })); + NativeModules.I18nManager = { + localeIdentifier: 'en-GB', + }; + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('adds platform context to events', async () => { + const sessionPlugin = await newPlatformContextPlugin(); + + const payloads: Payload[] = []; + const tracker = trackerCore({ + corePlugins: [sessionPlugin.plugin], + callback: (pb) => payloads.push(pb.build()), + base64: false, + }); + tracker.track(buildPageView({ pageUrl: 'http://localhost' })); + + expect(payloads.length).toBe(1); + const [payload] = payloads; + expect(payload?.co).toBeDefined(); + expect(payload?.co).toContain(MOBILE_CONTEXT_SCHEMA); + expect(payload?.co).toContain('"33"'); + expect(payload?.co).toContain('"sdk_gphone64_arm64"'); + expect(payload?.co).toContain('"Google"'); + expect(payload?.co).toContain('"Google"'); + expect(payload?.co).toContain('"en-GB"'); + }); +}); diff --git a/trackers/react-native-tracker/test/plugins/platform_context_ios.test.ts b/trackers/react-native-tracker/test/plugins/platform_context_ios.test.ts new file mode 100644 index 000000000..70beac1bd --- /dev/null +++ b/trackers/react-native-tracker/test/plugins/platform_context_ios.test.ts @@ -0,0 +1,162 @@ +import { buildPageView, Payload, trackerCore } from '@snowplow/tracker-core'; +import { newPlatformContextPlugin } from '../../src/plugins/platform_context'; +import { NativeModules } from 'react-native'; +import { MOBILE_CONTEXT_SCHEMA } from '../../src/constants'; + +describe('PlatformContextPlugin on iOS', () => { + beforeAll(() => { + jest.mock('react-native/Libraries/Utilities/Platform', () => ({ + OS: 'ios', + Version: '18.0', + constants: { + forceTouchAvailable: false, + interfaceIdiom: 'phone', + isMacCatalyst: false, + isTesting: false, + osVersion: '18.0', + systemName: 'iOS', + }, + isMacCatalyst: false, + isPad: false, + isTV: false, + isVision: false, + select: () => null, + })); + NativeModules.SettingsManager = { + settings: { + AppleLanguages: ['en-GB'], + }, + }; + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('adds platform context to events', async () => { + const sessionPlugin = await newPlatformContextPlugin(); + + const payloads: Payload[] = []; + const tracker = trackerCore({ + corePlugins: [sessionPlugin.plugin], + callback: (pb) => payloads.push(pb.build()), + base64: false, + }); + tracker.track(buildPageView({ pageUrl: 'http://localhost' })); + + expect(payloads.length).toBe(1); + const [payload] = payloads; + expect(payload?.co).toBeDefined(); + expect(payload?.co).toContain(MOBILE_CONTEXT_SCHEMA); + expect(payload?.co).toContain('"iOS"'); + expect(payload?.co).toContain('"18.0"'); + expect(payload?.co).toContain('"en-GB"'); + }); + + it('does not add platform context to events if disabled', async () => { + const sessionPlugin = await newPlatformContextPlugin({ platformContext: false }); + + const payloads: Payload[] = []; + const tracker = trackerCore({ + corePlugins: [sessionPlugin.plugin], + callback: (pb) => payloads.push(pb.build()), + base64: false, + }); + tracker.track(buildPageView({ pageUrl: 'http://localhost' })); + + expect(payloads.length).toBe(1); + const [payload] = payloads; + expect(payload?.co ?? '').not.toContain(MOBILE_CONTEXT_SCHEMA); + }); + + it('skips properties not enabled', async () => { + const sessionPlugin = await newPlatformContextPlugin({ platformContextProperties: [] }); + + const payloads: Payload[] = []; + const tracker = trackerCore({ + corePlugins: [sessionPlugin.plugin], + callback: (pb) => payloads.push(pb.build()), + base64: false, + }); + tracker.track(buildPageView({ pageUrl: 'http://localhost' })); + + expect(payloads.length).toBe(1); + const [payload] = payloads; + expect(payload?.co).toBeDefined(); + expect(payload?.co).toContain(MOBILE_CONTEXT_SCHEMA); + expect(payload?.co).toContain('"iOS"'); + expect(payload?.co).not.toContain('"en-GB"'); + }); + + it('overrides properties using the retriever', async () => { + const sessionPlugin = await newPlatformContextPlugin({ + platformContextRetriever: { + getOsType: () => Promise.resolve('Android'), + getOsVersion: () => Promise.resolve('11.0'), + getDeviceModel: () => Promise.resolve('Galaxy S21'), + getDeviceManufacturer: () => Promise.resolve('Samsung'), + getCarrier: () => Promise.resolve('Vodafone'), + getNetworkType: () => Promise.resolve('wifi'), + getNetworkTechnology: () => Promise.resolve('5G'), + getAppleIdfa: () => Promise.resolve('my-idfa'), + getAppleIdfv: () => Promise.resolve('my-idfv'), + getAvailableStorage: () => Promise.resolve(1000000000), + getTotalStorage: () => Promise.resolve(2000000000), + getPhysicalMemory: () => Promise.resolve(8000000000), + getAppAvailableMemory: () => Promise.resolve(2000000000), + getBatteryLevel: () => Promise.resolve(50), + getBatteryState: () => Promise.resolve('full'), + getLowPowerMode: () => Promise.resolve(false), + isPortrait: () => Promise.resolve(true), + getResolution: () => Promise.resolve('1920x1080'), + getScale: () => Promise.resolve(2), + getLanguage: () => Promise.resolve('en-US'), + getAndroidIdfa: () => Promise.resolve('my-android-idfa'), + getSystemAvailableMemory: () => Promise.resolve(2000000000), + getAppSetId: () => Promise.resolve('my-app-set'), + getAppSetIdScope: () => Promise.resolve('my-app-set-scope'), + }, + }); + + const payloads: Payload[] = []; + const tracker = trackerCore({ + corePlugins: [sessionPlugin.plugin], + callback: (pb) => payloads.push(pb.build()), + base64: false, + }); + tracker.track(buildPageView({ pageUrl: 'http://localhost' })); + + expect(payloads.length).toBe(1); + const [payload] = payloads; + expect(payload?.co).toBeDefined(); + const entities = JSON.parse(payload?.co as string).data; + const mobileContext = entities.find((entity: any) => entity.schema === MOBILE_CONTEXT_SCHEMA); + expect(mobileContext).toBeDefined(); + expect(mobileContext.data).toMatchObject({ + osType: 'Android', + osVersion: '11.0', + deviceModel: 'Galaxy S21', + deviceManufacturer: 'Samsung', + carrier: 'Vodafone', + networkType: 'wifi', + networkTechnology: '5G', + appleIdfa: 'my-idfa', + appleIdfv: 'my-idfv', + availableStorage: 1000000000, + totalStorage: 2000000000, + physicalMemory: 8000000000, + appAvailableMemory: 2000000000, + batteryLevel: 50, + batteryState: 'full', + lowPowerMode: false, + isPortrait: true, + resolution: '1920x1080', + scale: 2, + language: 'en-US', + androidIdfa: 'my-android-idfa', + systemAvailableMemory: 2000000000, + appSetId: 'my-app-set', + appSetIdScope: 'my-app-set-scope', + }); + }); +}); diff --git a/trackers/react-native-tracker/test/tracker.test.ts b/trackers/react-native-tracker/test/tracker.test.ts index 2305fb1a1..b39df33f1 100644 --- a/trackers/react-native-tracker/test/tracker.test.ts +++ b/trackers/react-native-tracker/test/tracker.test.ts @@ -1,4 +1,5 @@ import { getTracker, newTracker, removeAllTrackers, removeTracker } from '../src'; +import { MOBILE_CONTEXT_SCHEMA } from '../src/constants'; function createMockFetch(status: number, requests: Request[]) { return async (input: Request) => { @@ -92,6 +93,52 @@ describe('Tracker', () => { expect(pluginCalled).toBe(true); }); + it('tracks a platform context entity along with events unless disabled', async () => { + jest.mock('react-native/Libraries/Utilities/Platform', () => ({ + OS: 'ios', + Version: '18.0', + constants: { + osVersion: '18.0', + systemName: 'iOS', + }, + select: () => null, + })); + + const tracker = await newTracker({ + namespace: 'test', + endpoint: 'http://localhost:9090', + customFetch: mockFetch, + }); + + tracker.trackPageViewEvent({ + pageUrl: 'http://localhost:9090', + pageTitle: 'Home', + }); + + await tracker.flush(); + const [request] = requests; + const payload = await request?.json(); + expect(payload.data.length).toBe(1); + + const [event] = payload.data; + expect(event.co).toBeDefined(); + expect(event.co).toContain(MOBILE_CONTEXT_SCHEMA); + + tracker.disablePlatformContext(); + tracker.trackPageViewEvent({ + pageUrl: 'http://localhost:9090', + pageTitle: 'Home', + }); + + await tracker.flush(); + const [, request2] = requests; + const payload2 = await request2?.json(); + expect(payload2.data.length).toBe(1); + + const [event2] = payload2.data; + expect(event2.co ?? '').not.toContain(MOBILE_CONTEXT_SCHEMA); + }); + describe('Global contexts', () => { it('adds a global context', async () => { const tracker = await newTracker({ @@ -122,10 +169,9 @@ describe('Tracker', () => { const [event] = payload.data; expect(event.co).toBeDefined(); const context = JSON.parse(event.co as string); - expect(context.data.length).toBe(1); - const [{ schema, data }] = context.data; + expect(context.data.length).toBeGreaterThanOrEqual(1); + const { data } = context.data.find((c: any) => c.schema === 'iglu:com.acme/user/jsonschema/1-0-0'); - expect(schema).toBe('iglu:com.acme/user/jsonschema/1-0-0'); expect(data.userType).toBe('tester'); }); @@ -157,7 +203,7 @@ describe('Tracker', () => { expect(payload.data.length).toBe(1); const [event] = payload.data; - expect(event.co).toBeUndefined(); + expect(event.co ?? '').not.toContain(context.schema); }); }); });