UNPKG

5.22 kBJavaScriptView Raw
1import { Platform, Dimensions } from 'react-native';
2import Constants from 'expo-constants';
3
4import { ScreenHit, PageHit, Event, Serializable } from './hits';
5
6const { width, height } = Dimensions.get('window');
7
8let defaultOptions = { debug: false };
9
10let webViewUserAgent = null;
11const getWebViewUserAgent = async (options) => {
12 return new Promise((resolve) => {
13 if (options.userAgent) {
14 webViewUserAgent = options.userAgent;
15 return resolve(options.userAgent);
16 }
17 if (webViewUserAgent) return resolve(webViewUserAgent);
18 Constants.getWebViewUserAgentAsync()
19 .then(userAgent => {
20 webViewUserAgent = userAgent;
21 resolve(userAgent);
22 })
23 .catch(() => resolve('unknown user agent'))
24 });
25}
26
27export default class Analytics {
28 customDimensions = []
29 customMetrics = []
30
31 constructor(propertyId, additionalParameters = {}, options = defaultOptions){
32 this.propertyId = propertyId;
33 this.options = options;
34 this.clientId = Constants.deviceId;
35 this.parameters = {
36 an: Constants.manifest.name,
37 aid: Constants.manifest.slug,
38 av: Constants.manifest.version,
39 sr: `${width}x${height}`,
40 ...additionalParameters
41 };
42
43 this.promiseGetWebViewUserAgentAsync = getWebViewUserAgent(options)
44 .then(userAgent => {
45 this.userAgent = userAgent;
46 if(this.options.debug){
47 console.log(`[expo-analytics] UserAgent=${userAgent}`);
48 console.log(`[expo-analytics] Additional parameters=`, this.parameters);
49 }
50 });
51 }
52
53 hit(hit){
54 // send only after the user agent is saved
55 return this.promiseGetWebViewUserAgentAsync
56 .then(() => this.send(hit));
57 }
58
59 event(event){
60 // send only after the user agent is saved
61 return this.promiseGetWebViewUserAgentAsync
62 .then(() => this.send(event));
63 }
64
65 addParameter(name, value){
66 this.parameters[name] = value;
67 }
68
69 addCustomDimension(index, value){
70 this.customDimensions[index] = value;
71 }
72
73 removeCustomDimension(index){
74 delete this.customDimensions[index];
75 }
76
77 addCustomMetric(index, value) {
78 this.customMetrics[index] = value;
79 }
80
81 removeCustomMetric(index) {
82 delete this.customMetrics[index];
83 }
84
85 send(hit) {
86 /* format: https://www.google-analytics.com/collect? +
87 * &tid= GA property ID (required)
88 * &v= GA protocol version (always 1) (required)
89 * &t= hit type (pageview / screenview)
90 * &dp= page name (if hit type is pageview)
91 * &cd= screen name (if hit type is screenview)
92 * &cid= anonymous client ID (optional if uid is given)
93 * &uid= user id (optional if cid is given)
94 * &ua= user agent override
95 * &an= app name (required for any of the other app parameters to work)
96 * &aid= app id
97 * &av= app version
98 * &sr= screen resolution
99 * &cd{n}= custom dimensions
100 * &cm{n}= custom metrics
101 * &z= cache buster (prevent browsers from caching GET requests -- should always be last)
102 *
103 * Ecommerce track support (transaction)
104 * &ti= transaction The transaction ID. (e.g. 1234)
105 * &ta= The store or affiliation from which this transaction occurred (e.g. Acme Clothing).
106 * &tr= Specifies the total revenue or grand total associated with the transaction (e.g. 11.99). This value may include shipping, tax costs, or other adjustments to total revenue that you want to include as part of your revenue calculations.
107 * &tt= Specifies the total shipping cost of the transaction. (e.g. 5)
108 *
109 * Ecommerce track support (addItem)
110 * &ti= transaction The transaction ID. (e.g. 1234)
111 * &in= The item name. (e.g. Fluffy Pink Bunnies)
112 * &ip= The individual, unit, price for each item. (e.g. 11.99)
113 * &iq= The number of units purchased in the transaction. If a non-integer value is passed into this field (e.g. 1.5), it will be rounded to the closest integer value.
114 * &ic= TSpecifies the SKU or item code. (e.g. SKU47)
115 * &iv= The category to which the item belongs (e.g. Party Toys)
116 */
117
118 const customDimensions = this.customDimensions.map((value, index) => `cd${index}=${value}`).join('&');
119 const customMetrics = this.customMetrics.map((value, index) => `cm${index}=${value}`).join('&');
120
121 const params = new Serializable(this.parameters).toQueryString();
122
123 const url = `https://www.google-analytics.com/collect?tid=${this.propertyId}&v=1&cid=${this.clientId}&${hit.toQueryString()}&${params}&${customDimensions}&${customMetrics}&z=${Math.round(Math.random() * 1e8)}`;
124
125 let options = {
126 method: 'get',
127 headers: {
128 'User-Agent': this.userAgent
129 }
130 }
131
132 if(this.options.debug){
133 console.log(`[expo-analytics] Sending GET request to ${url}`);
134 }
135
136 return fetch(url, options);
137 }
138
139}