Skip to content

Commit 594e7a2

Browse files
authored
Integrate with new mobile interfaces (#19)
* Add initial implementation and an Android test * Add unit tests * Tidy code * Tidy code again * Update example app * Update example schema * Remove unused null check * Export a function to check for mobile interfaces * Fix type description * Update method signature to match the others * Update README
1 parent 827459c commit 594e7a2

File tree

8 files changed

+5575
-61
lines changed

8 files changed

+5575
-61
lines changed

README.md

+29-27
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ Snowplow is a scalable open-source platform for rich, high quality, low-latency
1111

1212
## Snowplow WebView Tracker Overview
1313

14-
The Snowplow WebView Tracker allows you to add analytics to your Web views embedded in mobile apps when using a [Snowplow][snowplow] pipeline.
14+
The Snowplow WebView Tracker allows you to add analytics to your WebViews embedded in mobile apps when using a [Snowplow][snowplow] pipeline.
1515

16-
The WebView tracker should be integrated in Web apps used in Web views within native mobile apps. The tracker provides APIs to track Snowplow events. It forwards the events to the native app code to be tracked by the Snowplow mobile trackers ([iOS][ios-tracker], [Android tracker][android-tracker], or [React Native][react-native-tracker]). The diagram below shows the interaction of the WebView and mobile trackers in hybrid apps.
16+
The WebView tracker should be integrated in Web apps used in WebViews within native mobile apps. The tracker provides APIs to track Snowplow events. It forwards the events to the native app code to be tracked by the Snowplow mobile trackers ([iOS][ios-tracker], [Android][android-tracker], or [React Native][react-native-tracker]). The diagram below shows the interaction of the WebView and mobile trackers in hybrid apps.
1717

1818
```mermaid
1919
flowchart TB
@@ -44,8 +44,6 @@ end
4444
nativeTracker -- "Sends tracked events" --> collector
4545
```
4646

47-
**Technical documentation can be found for each tracker in our [Hybrid Apps accelerator][webview-docs].**
48-
4947
## Quick Start
5048

5149
### Installation from npm
@@ -59,10 +57,10 @@ npm install --save @snowplow/webview-tracker
5957
You will then be able to use the functions provided by the WebView tracker as follows:
6058

6159
```typescript
62-
import { trackSelfDescribingEvent } from '@snowplow/webview-tracker';
60+
import { trackWebViewEvent } from '@snowplow/webview-tracker';
6361
```
6462

65-
In addition, you will need to install the iOS or Android tracker in your native code and configure and initialize a tracker (see the [mobile tracker docs][mobile-tracker-setup-docs]). Afterwards, you will be able to subscribe to and track the events from the WebView tracker in a Web view by calling `Snowplow.subscribeToWebViewEvents(webView)`.
63+
In addition, you will need to install the [iOS][ios-tracker], [Android][android-tracker], or [React Native][react-native-tracker] tracker in your native code and configure and initialize a tracker. Afterwards, you will be able to subscribe to and track the events from the WebView tracker in a WebView.
6664

6765
### Installation with the Snowplow tag
6866

@@ -79,32 +77,36 @@ You may download the `sp.js` file from the Releases section Github, self-host it
7977
To track events, simply call their corresponding functions given the event data:
8078

8179
```javascript
82-
trackSelfDescribingEvent({
80+
trackWebViewEvent({
81+
properties: {
82+
eventName: 'ue',
83+
trackerVersion: 'webview',
84+
},
8385
event: {
84-
schema: 'iglu:com.example_company/save_game/jsonschema/1-0-2',
85-
data: {
86-
'saveId': '4321',
87-
'level': 23,
88-
'difficultyLevel': 'HARD',
89-
'dlContent': true
90-
}
91-
}
92-
});
86+
schema:
87+
'iglu:com.snowplowanalytics.snowplow/button_click/jsonschema/1-0-0',
88+
data: {
89+
label: 'webview test',
90+
},
91+
},
92+
});
9393
```
9494

9595
In case you loaded the tracker using the Snowplow tag, you will be able to access the APIs using `window.snowplow`:
9696

9797
```javascript
98-
window.snowplow('trackSelfDescribingEvent', {
98+
window.snowplow('trackWebViewEvent', {
99+
properties: {
100+
eventName: 'ue',
101+
trackerVersion: 'webview',
102+
},
99103
event: {
100-
schema: 'iglu:com.example_company/save_game/jsonschema/1-0-2',
101-
data: {
102-
'saveId': '4321',
103-
'level': 23,
104-
'difficultyLevel': 'HARD',
105-
'dlContent': true
106-
}
107-
}
104+
schema:
105+
'iglu:com.snowplowanalytics.snowplow/button_click/jsonschema/1-0-0',
106+
data: {
107+
label: 'webview test',
108+
},
109+
},
108110
});
109111
```
110112

@@ -113,14 +115,14 @@ Please refer to the [tracker documentation][webview-docs] to learn more about th
113115
## Find Out More
114116

115117
| Technical Docs |
116-
|---------------------------------------|
118+
| ------------------------------------- |
117119
| [![i1][techdocs-image]][webview-docs] |
118120
| [Technical Docs][webview-docs] |
119121

120122
## Maintainers
121123

122124
| Contributing |
123-
|----------------------------------------------|
125+
| -------------------------------------------- |
124126
| [![i4][contributing-image]](CONTRIBUTING.md) |
125127
| [Contributing](CONTRIBUTING.md) |
126128

example/src/App.js

+58-22
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,70 @@
11
import logo from './logo.svg';
22
import './App.css';
3-
import { trackSelfDescribingEvent, trackPageView, trackScreenView, trackStructEvent } from '@snowplow/webview-tracker';
3+
import {
4+
trackSelfDescribingEvent,
5+
trackPageView,
6+
trackScreenView,
7+
trackStructEvent,
8+
trackWebViewEvent,
9+
} from '@snowplow/webview-tracker';
410
import { v4 as uuidv4 } from 'uuid';
511

612
function trackEvents() {
7-
trackSelfDescribingEvent({
8-
event: {
9-
schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1',
10-
data: {
11-
targetUrl: 'http://a-target-url.com'
12-
}
13+
trackWebViewEvent(
14+
{
15+
properties: {
16+
eventName: 'ue',
17+
trackerVersion: 'webview',
18+
useragent: 'useragent',
19+
},
20+
event: {
21+
schema:
22+
'iglu:com.snowplowanalytics.snowplow/button_click/jsonschema/1-0-0',
23+
data: {
24+
label: 'webview test',
25+
},
26+
},
27+
context: [
28+
{
29+
schema:
30+
'iglu:com.apple.swiftui/open_immersive_space/jsonschema/1-0-0',
31+
data: {},
32+
},
33+
],
1334
},
14-
context: [
15-
{
16-
schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1',
35+
['sp1']
36+
);
37+
38+
trackSelfDescribingEvent(
39+
{
40+
event: {
41+
schema:
42+
'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1',
1743
data: {
18-
targetUrl: 'http://in-context.com'
19-
}
20-
}
21-
],
22-
}, ['sp1']);
44+
targetUrl: 'http://a-target-url.com',
45+
},
46+
},
47+
context: [
48+
{
49+
schema:
50+
'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1',
51+
data: {
52+
targetUrl: 'http://in-context.com',
53+
},
54+
},
55+
],
56+
},
57+
['sp1']
58+
);
2359

2460
trackPageView();
2561

2662
trackStructEvent({
27-
category: 'cat', action: 'act', property: 'prop', label: 'lbl', value: 10
63+
category: 'cat',
64+
action: 'act',
65+
property: 'prop',
66+
label: 'lbl',
67+
value: 10,
2868
});
2969

3070
trackScreenView({
@@ -43,12 +83,8 @@ function App() {
4383
<div className="App">
4484
<header className="App-header">
4585
<img src={logo} className="App-logo" alt="logo" />
46-
<p>
47-
Hello from a Webview!
48-
</p>
49-
<button onClick={trackEvents}>
50-
Track events
51-
</button>
86+
<p>Hello from a Webview!</p>
87+
<button onClick={trackEvents}>Track events</button>
5288
</header>
5389
</div>
5490
);

src/api.ts

+76-12
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,40 @@ export interface SelfDescribingEvent {
3838
}
3939

4040
/**
41-
* A Structured Event
42-
* A classic style of event tracking, allows for easier movement between analytics
43-
* systems. A loosely typed event, creating a Self Describing event is preferred, but
44-
* useful for interoperability.
41+
* Event properties that are sent directly, not as part of a self-describing schema.
42+
* These properties will have their own column in the warehouse event table.
4543
*/
46-
export interface StructuredEvent {
47-
/** Name you for the group of objects you want to track e.g. "media", "ecomm". */
48-
category: string;
49-
/** Defines the type of user interaction for the web object. */
50-
action: string;
51-
/** Identifies the specific object being actioned. */
44+
export interface AtomicProperties {
45+
/** Type of event, e.g. "pp" for page ping. */
46+
eventName?: string;
47+
/** Version of the tracker used. */
48+
trackerVersion?: string;
49+
/** The browser useragent. */
50+
useragent?: string;
51+
/** For page view events. The page URL. */
52+
url?: string;
53+
/** For page view events. The page title. */
54+
title?: string;
55+
/** For page view events. The referrer URL. */
56+
referrer?: string;
57+
/** For structured events. Name for the group of objects you want to track. */
58+
category?: string;
59+
/** For structured events. Defines the type of user interaction for the web object. */
60+
action?: string;
61+
/** For structured events. Identifies the specific object being actioned. */
5262
label?: string;
53-
/** Describes the object or the action performed on it. */
63+
/** For structured events. Describes the object or the action performed on it. */
5464
property?: string;
55-
/** Quantifies or further describes the user action. */
65+
/** For structured events. Quantifies or further describes the user action. */
5666
value?: number;
67+
/** For page ping events. The minimum X offset. */
68+
minXOffset?: number;
69+
/** For page ping events. The maximum X offset. */
70+
maxXOffset?: number;
71+
/** For page ping events. The minimum Y offset. */
72+
minYOffset?: number;
73+
/** For page ping events. The maximum Y offset. */
74+
maxYOffset?: number;
5775
}
5876

5977
/**
@@ -91,12 +109,36 @@ interface FullPageViewEvent extends PageViewEvent {
91109
referrer?: string;
92110
}
93111

112+
/**
113+
* A Structured Event
114+
* A classic style of event tracking, allows for easier movement between analytics
115+
* systems. A loosely typed event, creating a Self Describing event is preferred, but
116+
* useful for interoperability.
117+
*/
118+
export interface StructuredEvent {
119+
/** Name you for the group of objects you want to track e.g. "media", "ecomm". */
120+
category: string;
121+
/** Defines the type of user interaction for the web object. */
122+
action: string;
123+
/** Identifies the specific object being actioned. */
124+
label?: string;
125+
/** Describes the object or the action performed on it. */
126+
property?: string;
127+
/** Quantifies or further describes the user action. */
128+
value?: number;
129+
}
130+
94131
/** Additional data points to set when tracking an event */
95132
export interface CommonEventProperties {
96133
/** Add context to an event by setting an Array of Self Describing JSON */
97134
context?: Array<SelfDescribingJson> | null;
98135
}
99136

137+
export interface WebViewEvent {
138+
properties: AtomicProperties;
139+
event?: SelfDescribingEvent;
140+
}
141+
100142
/** Interface for communicating with the Android mobile tracker */
101143
export type SnowplowWebInterface = {
102144
trackSelfDescribingEvent: (
@@ -134,6 +176,16 @@ export type SnowplowWebInterface = {
134176
) => void;
135177
};
136178

179+
/** Interface for communicating with the Android mobile tracker from v6.1+ onwards */
180+
export type SnowplowWebInterfaceV2 = {
181+
trackWebViewEvent: (
182+
atomicProperties: string,
183+
selfDescribingEventData?: string | null,
184+
context?: string | null,
185+
trackers?: Array<string> | null
186+
) => void;
187+
};
188+
137189
/** Interface for communicating with the iOS mobile tracker */
138190
export type WebkitMessageHandler = {
139191
postMessage: (message: {
@@ -148,6 +200,16 @@ export type WebkitMessageHandler = {
148200
}) => void;
149201
};
150202

203+
/** Interface for communicating with the iOS mobile tracker from v6.1+ onwards */
204+
export type WebkitMessageHandlerV2 = {
205+
postMessage: (message: {
206+
atomicProperties: string;
207+
selfDescribingEventData?: string | null;
208+
context?: string | null;
209+
trackers?: Array<string> | null;
210+
}) => void;
211+
};
212+
151213
/** Interface for communicating with the React Native tracker */
152214
export type ReactNativeInterface = {
153215
postMessage: (message: string) => void;
@@ -156,9 +218,11 @@ export type ReactNativeInterface = {
156218
declare global {
157219
interface Window {
158220
SnowplowWebInterface?: SnowplowWebInterface;
221+
SnowplowWebInterfaceV2?: SnowplowWebInterfaceV2;
159222
webkit?: {
160223
messageHandlers?: {
161224
snowplow?: WebkitMessageHandler;
225+
snowplowV2?: WebkitMessageHandlerV2;
162226
};
163227
};
164228
ReactNativeWebView?: ReactNativeInterface;

0 commit comments

Comments
 (0)