onerway-analytics 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/dist/bundle/index.js +320 -176
- package/dist/bundle/index.js.map +4 -4
- package/dist/core/analytics.d.ts +2 -3
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js +35 -132
- package/dist/core/delivery-queue.d.ts +41 -0
- package/dist/core/delivery-queue.d.ts.map +1 -0
- package/dist/core/delivery-queue.js +248 -0
- package/dist/core/sender.d.ts +7 -3
- package/dist/core/sender.d.ts.map +1 -1
- package/dist/core/sender.js +42 -46
- package/dist/types/index.d.ts +5 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/package.json +7 -3
- package/dist/core/analytics.test.d.ts +0 -2
- package/dist/core/analytics.test.d.ts.map +0 -1
- package/dist/core/analytics.test.js +0 -169
- package/dist/core/ga-adapter.d.ts +0 -11
- package/dist/core/ga-adapter.d.ts.map +0 -1
- package/dist/core/ga-adapter.js +0 -66
- package/dist/core/ga-loader.d.ts +0 -10
- package/dist/core/ga-loader.d.ts.map +0 -1
- package/dist/core/ga-loader.js +0 -34
- package/dist/core/ga-manager.d.ts +0 -24
- package/dist/core/ga-manager.d.ts.map +0 -1
- package/dist/core/ga-manager.js +0 -64
package/dist/types/index.d.ts
CHANGED
|
@@ -102,6 +102,10 @@ export interface AnalyticsConfig {
|
|
|
102
102
|
gtm?: GTMConfig;
|
|
103
103
|
disableServer?: boolean;
|
|
104
104
|
sampleRate?: number;
|
|
105
|
+
/** Persist key events until HTTP acknowledgement (24h / 500-event bound).
|
|
106
|
+
* Enable only for applications whose event properties are safe to store locally.
|
|
107
|
+
*/
|
|
108
|
+
persistKeyEvents?: boolean;
|
|
105
109
|
/** @deprecated use appKey instead */
|
|
106
110
|
appId?: string;
|
|
107
111
|
}
|
|
@@ -135,7 +139,7 @@ export interface RetryEntry {
|
|
|
135
139
|
timer: ReturnType<typeof setTimeout> | null;
|
|
136
140
|
}
|
|
137
141
|
export declare const API_KEY_MAP: Record<string, string>;
|
|
138
|
-
export declare const SDK_VERSION = "1.
|
|
142
|
+
export declare const SDK_VERSION = "1.3.2";
|
|
139
143
|
export declare const DEFAULT_CONFIG: {
|
|
140
144
|
readonly debug: false;
|
|
141
145
|
readonly autoTrack: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC;AAE9G,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,EAAE,eAAe,CAAC;IAClC,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export const API_KEY_MAP = {
|
|
|
8
8
|
prod: 'HUk5Kogyuv9zH5qDA2qSCjVEnhanSkf8',
|
|
9
9
|
production: 'HUk5Kogyuv9zH5qDA2qSCjVEnhanSkf8',
|
|
10
10
|
};
|
|
11
|
-
export const SDK_VERSION = '1.
|
|
11
|
+
export const SDK_VERSION = '1.3.2';
|
|
12
12
|
export const DEFAULT_CONFIG = {
|
|
13
13
|
debug: false,
|
|
14
14
|
autoTrack: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onerway-analytics",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Onrway Analytics SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -17,12 +17,15 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "
|
|
20
|
+
"build": "node scripts/build.cjs",
|
|
21
21
|
"build:browser": "node build-browser.js",
|
|
22
22
|
"build:watch": "tsc --watch",
|
|
23
23
|
"lint": "eslint src --ext .ts",
|
|
24
24
|
"test": "jest",
|
|
25
|
-
"typecheck": "tsc --noEmit"
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"test:browser": "npm run build:browser && node scripts/verify-delivery.cjs",
|
|
27
|
+
"prepack": "npm run build && npm run build:browser",
|
|
28
|
+
"test:browser:comparison": "npm run build:browser && node scripts/verify-checkout-comparison.cjs"
|
|
26
29
|
},
|
|
27
30
|
"keywords": [
|
|
28
31
|
"analytics",
|
|
@@ -38,6 +41,7 @@
|
|
|
38
41
|
"eslint": "^8.57.0",
|
|
39
42
|
"jest": "^29.7.0",
|
|
40
43
|
"jest-environment-jsdom": "^30.4.1",
|
|
44
|
+
"playwright": "^1.63.0",
|
|
41
45
|
"ts-jest": "^29.1.0",
|
|
42
46
|
"typescript": "^5.3.0"
|
|
43
47
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.test.d.ts","sourceRoot":"","sources":["../../src/core/analytics.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { createAnalytics } from '../core/analytics';
|
|
3
|
-
import { StorageQueue } from '../core/storage';
|
|
4
|
-
function createMockXHR() {
|
|
5
|
-
const calls = [];
|
|
6
|
-
globalThis.XMLHttpRequest = class {
|
|
7
|
-
constructor() {
|
|
8
|
-
this._url = '';
|
|
9
|
-
this._body = '';
|
|
10
|
-
this._headers = {};
|
|
11
|
-
this.status = 0;
|
|
12
|
-
this.statusText = '';
|
|
13
|
-
this.readyState = 0;
|
|
14
|
-
this.onload = null;
|
|
15
|
-
this.onerror = null;
|
|
16
|
-
this.ontimeout = null;
|
|
17
|
-
this.timeout = 0;
|
|
18
|
-
}
|
|
19
|
-
open(_method, url) {
|
|
20
|
-
this._url = url;
|
|
21
|
-
}
|
|
22
|
-
setRequestHeader(key, value) {
|
|
23
|
-
this._headers[key] = value;
|
|
24
|
-
}
|
|
25
|
-
send(body) {
|
|
26
|
-
this._body = body || '';
|
|
27
|
-
calls.push({ url: this._url, body: this._body, headers: { ...this._headers } });
|
|
28
|
-
setTimeout(() => {
|
|
29
|
-
this.status = 200;
|
|
30
|
-
this.statusText = 'OK';
|
|
31
|
-
this.readyState = 4;
|
|
32
|
-
if (this.onload)
|
|
33
|
-
this.onload({});
|
|
34
|
-
}, 0);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
return calls;
|
|
38
|
-
}
|
|
39
|
-
describe('Analytics SDK', () => {
|
|
40
|
-
let analytics;
|
|
41
|
-
let xhrCalls;
|
|
42
|
-
beforeEach(() => {
|
|
43
|
-
localStorage.clear();
|
|
44
|
-
sessionStorage.clear();
|
|
45
|
-
xhrCalls = createMockXHR();
|
|
46
|
-
analytics = createAnalytics({
|
|
47
|
-
appKey: 'test-app-id',
|
|
48
|
-
serverUrl: 'https://example.com/track',
|
|
49
|
-
apiKey: 'test-api-key',
|
|
50
|
-
debug: false,
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
afterEach(() => {
|
|
54
|
-
analytics.reset();
|
|
55
|
-
jest.restoreAllMocks();
|
|
56
|
-
});
|
|
57
|
-
describe('track', () => {
|
|
58
|
-
it('should send events on flush', async () => {
|
|
59
|
-
analytics.track('test_event', { custom_prop: 'value' });
|
|
60
|
-
analytics.flush();
|
|
61
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
62
|
-
expect(xhrCalls.length).toBeGreaterThanOrEqual(1);
|
|
63
|
-
const body = JSON.parse(xhrCalls[0].body);
|
|
64
|
-
const pageViewEvent = body.events.find((e) => e.event_name === 'page_view');
|
|
65
|
-
const testEvent = body.events.find((e) => e.event_name === 'test_event');
|
|
66
|
-
expect(pageViewEvent).toBeDefined();
|
|
67
|
-
expect(testEvent).toBeDefined();
|
|
68
|
-
expect(testEvent.event_properties.custom_prop).toBe('value');
|
|
69
|
-
});
|
|
70
|
-
it('should ignore invalid event name', async () => {
|
|
71
|
-
analytics.track('');
|
|
72
|
-
analytics.track(123);
|
|
73
|
-
analytics.flush();
|
|
74
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
75
|
-
if (xhrCalls.length > 0) {
|
|
76
|
-
const body = JSON.parse(xhrCalls[0].body);
|
|
77
|
-
const names = body.events.map((e) => e.event_name);
|
|
78
|
-
expect(names).not.toContain('');
|
|
79
|
-
expect(names).toContain('page_view');
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
describe('identify', () => {
|
|
84
|
-
it('should set user profile', () => {
|
|
85
|
-
analytics.identify('user-123', { name: 'Test User' });
|
|
86
|
-
const profile = analytics.getUserProfile();
|
|
87
|
-
expect(profile.userId).toBe('user-123');
|
|
88
|
-
expect(profile.attributes).toEqual({ name: 'Test User' });
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
describe('reset', () => {
|
|
92
|
-
it('should clear user profile and queue', () => {
|
|
93
|
-
analytics.identify('user-123', { name: 'Test User' });
|
|
94
|
-
analytics.track('some_event');
|
|
95
|
-
analytics.reset();
|
|
96
|
-
const profile = analytics.getUserProfile();
|
|
97
|
-
expect(profile.userId).toBeUndefined();
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
describe('configuration', () => {
|
|
101
|
-
it('should support appId backward compatibility', () => {
|
|
102
|
-
const analytics2 = createAnalytics({
|
|
103
|
-
appId: 'backward-compat-app',
|
|
104
|
-
serverUrl: 'https://example.com/track',
|
|
105
|
-
apiKey: 'test-api-key',
|
|
106
|
-
debug: false,
|
|
107
|
-
});
|
|
108
|
-
expect(analytics2.getClientId()).toBeDefined();
|
|
109
|
-
analytics2.reset();
|
|
110
|
-
});
|
|
111
|
-
it('should generate client_id on creation', () => {
|
|
112
|
-
const cid = analytics.getClientId();
|
|
113
|
-
expect(cid).toBeDefined();
|
|
114
|
-
expect(typeof cid).toBe('string');
|
|
115
|
-
expect(cid.length).toBeGreaterThan(0);
|
|
116
|
-
});
|
|
117
|
-
it('should generate session_id on creation', () => {
|
|
118
|
-
const sid = analytics.getSessionId();
|
|
119
|
-
expect(sid).toBeDefined();
|
|
120
|
-
expect(typeof sid).toBe('string');
|
|
121
|
-
expect(sid.length).toBeGreaterThan(0);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
describe('payload structure', () => {
|
|
125
|
-
it('should assemble correct request payload', async () => {
|
|
126
|
-
analytics.track('test_event', { scene: 'checkout.payment' });
|
|
127
|
-
analytics.flush();
|
|
128
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
129
|
-
expect(xhrCalls.length).toBeGreaterThanOrEqual(1);
|
|
130
|
-
const body = JSON.parse(xhrCalls[0].body);
|
|
131
|
-
expect(body.client_id).toBeDefined();
|
|
132
|
-
expect(body.session_id).toBeDefined();
|
|
133
|
-
expect(body.user_id).toBe('');
|
|
134
|
-
expect(body.user_properties).toBeUndefined();
|
|
135
|
-
expect(body.context).toBeDefined();
|
|
136
|
-
expect(body.context.app_key).toBe('test-app-id');
|
|
137
|
-
expect(body.context.sdk_version).toBeDefined();
|
|
138
|
-
expect(body.marketing).toBeDefined();
|
|
139
|
-
expect(body.events).toBeInstanceOf(Array);
|
|
140
|
-
const testEvent = body.events.find((e) => e.event_name === 'test_event');
|
|
141
|
-
expect(testEvent).toBeDefined();
|
|
142
|
-
expect(testEvent.event_id).toBeDefined();
|
|
143
|
-
expect(testEvent.timestamp).toBeGreaterThan(0);
|
|
144
|
-
expect(testEvent.key_event).toBe(false);
|
|
145
|
-
expect(testEvent.event_properties.scene).toBe('checkout.payment');
|
|
146
|
-
expect(testEvent.batch_ordering_id).toBeDefined();
|
|
147
|
-
expect(testEvent.batch_page_id).toBeDefined();
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
describe('StorageQueue', () => {
|
|
151
|
-
it('should persist and recover failed events', () => {
|
|
152
|
-
StorageQueue.clear();
|
|
153
|
-
StorageQueue.enqueue({
|
|
154
|
-
event_id: 'evt-1',
|
|
155
|
-
event_name: 'failed_event',
|
|
156
|
-
batch_event_index: 0,
|
|
157
|
-
batch_ordering_id: 'ord-1',
|
|
158
|
-
batch_page_id: 'page-1',
|
|
159
|
-
timestamp: Date.now(),
|
|
160
|
-
key_event: false,
|
|
161
|
-
event_properties: {},
|
|
162
|
-
});
|
|
163
|
-
const recovered = StorageQueue.recover();
|
|
164
|
-
expect(recovered.length).toBe(1);
|
|
165
|
-
expect(recovered[0].event_name).toBe('failed_event');
|
|
166
|
-
expect(StorageQueue.getQueueSize()).toBe(0);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { MarketingPayload } from '../types';
|
|
2
|
-
export interface GAEventOptions {
|
|
3
|
-
sessionId: string;
|
|
4
|
-
pageUrl: string;
|
|
5
|
-
referrer: string;
|
|
6
|
-
}
|
|
7
|
-
export declare function trackToGA(eventName: string, properties: Record<string, unknown>, options: GAEventOptions): void;
|
|
8
|
-
export declare function setGAUserId(userId: string | null): void;
|
|
9
|
-
export declare function setGAUserProperties(properties: Record<string, unknown>): void;
|
|
10
|
-
export declare function setGAMarketing(marketing: MarketingPayload): void;
|
|
11
|
-
//# sourceMappingURL=ga-adapter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ga-adapter.d.ts","sourceRoot":"","sources":["../../src/core/ga-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqBD,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,OAAO,EAAE,cAAc,GACtB,IAAI,CAqBN;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGvD;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAG7E;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAWhE"}
|
package/dist/core/ga-adapter.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// GA4 reserved event names — sending these as custom events causes silent drops
|
|
2
|
-
const GA4_RESERVED_NAMES = new Set([
|
|
3
|
-
'ad_activeview', 'ad_click', 'ad_exposure', 'ad_impression', 'ad_query',
|
|
4
|
-
'adunit_exposure', 'app_clear_data', 'app_exception', 'app_install',
|
|
5
|
-
'app_remove', 'app_update', 'app_upgrade', 'error', 'firebase_campaign',
|
|
6
|
-
'first_open', 'first_visit', 'in_app_purchase', 'notification_dismiss',
|
|
7
|
-
'notification_foreground', 'notification_open', 'notification_receive',
|
|
8
|
-
'os_update', 'session_start', 'user_engagement',
|
|
9
|
-
]);
|
|
10
|
-
// System/automated events — don't contribute to engagement_time_msec
|
|
11
|
-
const SYSTEM_EVENTS = new Set(['web_vital', 'error_event']);
|
|
12
|
-
function sanitizeEventName(name) {
|
|
13
|
-
let result = name.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
14
|
-
if (!/^[a-zA-Z]/.test(result))
|
|
15
|
-
result = 'e_' + result;
|
|
16
|
-
return result.slice(0, 40);
|
|
17
|
-
}
|
|
18
|
-
export function trackToGA(eventName, properties, options) {
|
|
19
|
-
if (typeof window === 'undefined' || !window.gtag)
|
|
20
|
-
return;
|
|
21
|
-
// Sanitize event name for GA4 compliance
|
|
22
|
-
const safeName = GA4_RESERVED_NAMES.has(eventName)
|
|
23
|
-
? `custom_${eventName}`.slice(0, 40)
|
|
24
|
-
: sanitizeEventName(eventName);
|
|
25
|
-
// Business properties first, then GA reserved fields override — prevents
|
|
26
|
-
// caller properties from corrupting session_id / page_location etc.
|
|
27
|
-
const params = { ...properties };
|
|
28
|
-
params.session_id = options.sessionId;
|
|
29
|
-
params.page_location = options.pageUrl;
|
|
30
|
-
params.page_referrer = options.referrer;
|
|
31
|
-
// engagement_time_msec only for user-facing events, not automated system events
|
|
32
|
-
if (!SYSTEM_EVENTS.has(eventName)) {
|
|
33
|
-
params.engagement_time_msec = 100;
|
|
34
|
-
}
|
|
35
|
-
window.gtag('event', safeName, params);
|
|
36
|
-
}
|
|
37
|
-
export function setGAUserId(userId) {
|
|
38
|
-
if (typeof window === 'undefined' || !window.gtag)
|
|
39
|
-
return;
|
|
40
|
-
window.gtag('set', { user_id: userId ?? undefined });
|
|
41
|
-
}
|
|
42
|
-
export function setGAUserProperties(properties) {
|
|
43
|
-
if (typeof window === 'undefined' || !window.gtag)
|
|
44
|
-
return;
|
|
45
|
-
window.gtag('set', 'user_properties', properties);
|
|
46
|
-
}
|
|
47
|
-
// Set UTM attribution once at session level — GA4 auto-associates with all
|
|
48
|
-
// subsequent events, no need to repeat on every event payload
|
|
49
|
-
export function setGAMarketing(marketing) {
|
|
50
|
-
if (typeof window === 'undefined' || !window.gtag)
|
|
51
|
-
return;
|
|
52
|
-
const params = {};
|
|
53
|
-
if (marketing.utm_source)
|
|
54
|
-
params.utm_source = marketing.utm_source;
|
|
55
|
-
if (marketing.utm_medium)
|
|
56
|
-
params.utm_medium = marketing.utm_medium;
|
|
57
|
-
if (marketing.utm_campaign)
|
|
58
|
-
params.utm_campaign = marketing.utm_campaign;
|
|
59
|
-
if (marketing.utm_term)
|
|
60
|
-
params.utm_term = marketing.utm_term;
|
|
61
|
-
if (marketing.utm_content)
|
|
62
|
-
params.utm_content = marketing.utm_content;
|
|
63
|
-
if (Object.keys(params).length > 0) {
|
|
64
|
-
window.gtag('set', params);
|
|
65
|
-
}
|
|
66
|
-
}
|
package/dist/core/ga-loader.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { GAConfig } from '../types';
|
|
2
|
-
declare global {
|
|
3
|
-
interface Window {
|
|
4
|
-
gtag: (...args: unknown[]) => void;
|
|
5
|
-
dataLayer: unknown[];
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export declare function loadGtagScript(measurementId: string): Promise<void>;
|
|
9
|
-
export declare function initGA(config: GAConfig): Promise<void>;
|
|
10
|
-
//# sourceMappingURL=ga-loader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ga-loader.d.ts","sourceRoot":"","sources":["../../src/core/ga-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QACnC,SAAS,EAAE,OAAO,EAAE,CAAC;KACtB;CACF;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAenE;AAED,wBAAsB,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB5D"}
|
package/dist/core/ga-loader.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export function loadGtagScript(measurementId) {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
// Check for existing script tag, not window.gtag — we define gtag before loading
|
|
4
|
-
if (document.querySelector(`script[src*="googletagmanager.com/gtag/js"]`)) {
|
|
5
|
-
resolve();
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
const script = document.createElement('script');
|
|
9
|
-
script.async = true;
|
|
10
|
-
script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
|
|
11
|
-
script.onload = () => resolve();
|
|
12
|
-
script.onerror = () => reject(new Error('Failed to load gtag.js'));
|
|
13
|
-
document.head.appendChild(script);
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
export async function initGA(config) {
|
|
17
|
-
if (!config.enabled || !config.measurementId)
|
|
18
|
-
return;
|
|
19
|
-
if (typeof window === 'undefined')
|
|
20
|
-
return;
|
|
21
|
-
// Must be defined BEFORE the script loads so gtag.js finds them on execution
|
|
22
|
-
window.dataLayer = window.dataLayer || [];
|
|
23
|
-
// gtag.js checks e.constructor == Arguments, so must push `arguments` not a rest-param array
|
|
24
|
-
window.gtag = function gtag() {
|
|
25
|
-
// eslint-disable-next-line prefer-rest-params
|
|
26
|
-
window.dataLayer.push(arguments);
|
|
27
|
-
};
|
|
28
|
-
window.gtag('js', new Date());
|
|
29
|
-
window.gtag('config', config.measurementId, {
|
|
30
|
-
send_page_view: config.sendPageView ?? false,
|
|
31
|
-
debug_mode: config.debugMode ?? false,
|
|
32
|
-
});
|
|
33
|
-
await loadGtagScript(config.measurementId);
|
|
34
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { GAConsentMode, GAConsentParams } from '../types';
|
|
2
|
-
declare global {
|
|
3
|
-
interface Window {
|
|
4
|
-
gtag: (...args: unknown[]) => void;
|
|
5
|
-
dataLayer: unknown[];
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export declare class GAManager {
|
|
9
|
-
private _initialized;
|
|
10
|
-
private _measurementId;
|
|
11
|
-
get ready(): boolean;
|
|
12
|
-
get measurementId(): string | undefined;
|
|
13
|
-
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
14
|
-
setUserId(userId: string | null): void;
|
|
15
|
-
setUserProperties(properties: Record<string, unknown>): void;
|
|
16
|
-
set(keyOrParams: string | Record<string, unknown>, value?: unknown): void;
|
|
17
|
-
config(params?: Record<string, unknown>): void;
|
|
18
|
-
consent(mode: GAConsentMode, params: GAConsentParams): void;
|
|
19
|
-
get(key: string, callback: (value: unknown) => void): void;
|
|
20
|
-
gtag(...args: unknown[]): void;
|
|
21
|
-
_init(measurementId: string): void;
|
|
22
|
-
_destroy(): void;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=ga-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ga-manager.d.ts","sourceRoot":"","sources":["../../src/core/ga-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAChB,MAAM,UAAU,CAAC;AAElB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QACnC,SAAS,EAAE,OAAO,EAAE,CAAC;KACtB;CACF;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAqB;IAE3C,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKpE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKtC,iBAAiB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5D,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IASzE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK9C,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI;IAK3D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAK1D,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAK9B,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAKlC,QAAQ,IAAI,IAAI;CAIjB"}
|
package/dist/core/ga-manager.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
export class GAManager {
|
|
2
|
-
constructor() {
|
|
3
|
-
this._initialized = false;
|
|
4
|
-
}
|
|
5
|
-
get ready() {
|
|
6
|
-
return this._initialized && typeof window !== 'undefined' && typeof window.gtag === 'function';
|
|
7
|
-
}
|
|
8
|
-
get measurementId() {
|
|
9
|
-
return this._measurementId;
|
|
10
|
-
}
|
|
11
|
-
track(eventName, properties) {
|
|
12
|
-
if (!this.ready)
|
|
13
|
-
return;
|
|
14
|
-
window.gtag('event', eventName, properties ?? {});
|
|
15
|
-
}
|
|
16
|
-
setUserId(userId) {
|
|
17
|
-
if (!this.ready)
|
|
18
|
-
return;
|
|
19
|
-
window.gtag('set', { user_id: userId ?? undefined });
|
|
20
|
-
}
|
|
21
|
-
setUserProperties(properties) {
|
|
22
|
-
if (!this.ready)
|
|
23
|
-
return;
|
|
24
|
-
window.gtag('set', 'user_properties', properties);
|
|
25
|
-
}
|
|
26
|
-
set(keyOrParams, value) {
|
|
27
|
-
if (!this.ready)
|
|
28
|
-
return;
|
|
29
|
-
if (typeof keyOrParams === 'string') {
|
|
30
|
-
window.gtag('set', keyOrParams, value);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
window.gtag('set', keyOrParams);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
config(params) {
|
|
37
|
-
if (!this.ready || !this._measurementId)
|
|
38
|
-
return;
|
|
39
|
-
window.gtag('config', this._measurementId, params ?? {});
|
|
40
|
-
}
|
|
41
|
-
consent(mode, params) {
|
|
42
|
-
if (!this.ready)
|
|
43
|
-
return;
|
|
44
|
-
window.gtag('consent', mode, params);
|
|
45
|
-
}
|
|
46
|
-
get(key, callback) {
|
|
47
|
-
if (!this.ready || !this._measurementId)
|
|
48
|
-
return;
|
|
49
|
-
window.gtag('get', this._measurementId, key, callback);
|
|
50
|
-
}
|
|
51
|
-
gtag(...args) {
|
|
52
|
-
if (typeof window === 'undefined' || !window.gtag)
|
|
53
|
-
return;
|
|
54
|
-
window.gtag(...args);
|
|
55
|
-
}
|
|
56
|
-
_init(measurementId) {
|
|
57
|
-
this._measurementId = measurementId;
|
|
58
|
-
this._initialized = true;
|
|
59
|
-
}
|
|
60
|
-
_destroy() {
|
|
61
|
-
this._initialized = false;
|
|
62
|
-
this._measurementId = undefined;
|
|
63
|
-
}
|
|
64
|
-
}
|