mytart 0.2.3 → 0.3.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 +34 -2
- package/dist/index.d.mts +28 -18
- package/dist/index.d.ts +28 -18
- package/dist/index.js +68 -46
- package/dist/index.mjs +68 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,10 +50,42 @@ await analytics.page({ url: 'https://example.com/pricing', name: 'Pricing' });
|
|
|
50
50
|
|
|
51
51
|
### Google Analytics 4
|
|
52
52
|
|
|
53
|
+
GA4 supports two modes via the `appType` option:
|
|
54
|
+
|
|
55
|
+
#### Server mode (default)
|
|
56
|
+
|
|
57
|
+
Uses the [GA4 Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/ga4) — direct HTTP calls, no browser APIs. Use this for Node.js, API routes, serverless functions, etc.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
{
|
|
61
|
+
provider: 'google-analytics',
|
|
62
|
+
measurementId: 'G-XXXXXXXXXX',
|
|
63
|
+
apiSecret: 'YOUR_SECRET',
|
|
64
|
+
enabled: true,
|
|
65
|
+
// appType defaults to 'server'
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Browser mode
|
|
70
|
+
|
|
71
|
+
Injects Google's official [gtag.js snippet](https://developers.google.com/tag-platform/gtagjs) into the page. Use this for client-side tracking in any framework (React, Vue, Svelte, plain HTML, etc.). No `apiSecret` needed.
|
|
72
|
+
|
|
53
73
|
```typescript
|
|
54
|
-
{
|
|
74
|
+
{
|
|
75
|
+
provider: 'google-analytics',
|
|
76
|
+
measurementId: 'G-XXXXXXXXXX',
|
|
77
|
+
appType: 'browser',
|
|
78
|
+
enabled: true,
|
|
79
|
+
}
|
|
55
80
|
```
|
|
56
81
|
|
|
82
|
+
When `appType: 'browser'` is set:
|
|
83
|
+
|
|
84
|
+
- The gtag.js script is loaded once on the first `track()`, `identify()`, or `page()` call
|
|
85
|
+
- All calls use the standard `gtag()` API — compatible with Google Tag Tester and Tag Assistant
|
|
86
|
+
- SSR-safe: silently succeeds when `window` is undefined (e.g. during server-side rendering)
|
|
87
|
+
- `apiSecret` is not required (and not used)
|
|
88
|
+
|
|
57
89
|
### Mixpanel
|
|
58
90
|
|
|
59
91
|
```typescript
|
|
@@ -187,7 +219,7 @@ All types are exported:
|
|
|
187
219
|
```typescript
|
|
188
220
|
import type {
|
|
189
221
|
MytartConfig, BaseProviderConfig, ProviderConfig, TrackOptions, IdentifyOptions, PageOptions,
|
|
190
|
-
TrackResult, MytartError, EventContext, ProviderName,
|
|
222
|
+
TrackResult, MytartError, EventContext, ProviderName, GoogleAnalyticsAppType,
|
|
191
223
|
GoogleAnalyticsConfig, MixpanelConfig, SegmentConfig,
|
|
192
224
|
AmplitudeConfig, PlausibleConfig, PostHogConfig,
|
|
193
225
|
} from 'mytart';
|
package/dist/index.d.mts
CHANGED
|
@@ -126,34 +126,44 @@ declare global {
|
|
|
126
126
|
dataLayer: unknown[];
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
(command: 'config', measurementId: string, config?: GtagConfig): void;
|
|
131
|
-
(command: 'event', eventName: string, params?: Record<string, unknown>): void;
|
|
132
|
-
(command: 'set', config: Record<string, unknown>): void;
|
|
133
|
-
(command: string, ...args: unknown[]): void;
|
|
134
|
-
}
|
|
135
|
-
interface GtagConfig {
|
|
136
|
-
send_page_view?: boolean;
|
|
137
|
-
page_title?: string;
|
|
138
|
-
page_location?: string;
|
|
139
|
-
page_referrer?: string;
|
|
140
|
-
user_id?: string;
|
|
141
|
-
[key: string]: unknown;
|
|
142
|
-
}
|
|
129
|
+
type GtagFn = (...args: unknown[]) => void;
|
|
143
130
|
declare class GoogleAnalyticsProvider extends BaseProvider {
|
|
144
131
|
readonly name = "google-analytics";
|
|
145
132
|
private readonly config;
|
|
146
133
|
private readonly http;
|
|
147
134
|
private readonly endpoint;
|
|
148
135
|
private readonly isBrowser;
|
|
149
|
-
private
|
|
136
|
+
private gtagReady;
|
|
150
137
|
constructor(config: GoogleAnalyticsConfig);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Initializes the gtag.js snippet exactly as Google's official documentation
|
|
140
|
+
* specifies. This mirrors the standard snippet:
|
|
141
|
+
*
|
|
142
|
+
* <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
|
|
143
|
+
* <script>
|
|
144
|
+
* window.dataLayer = window.dataLayer || [];
|
|
145
|
+
* function gtag(){dataLayer.push(arguments);}
|
|
146
|
+
* gtag('js', new Date());
|
|
147
|
+
* gtag('config', 'TAG_ID');
|
|
148
|
+
* </script>
|
|
149
|
+
*
|
|
150
|
+
* Key details:
|
|
151
|
+
* - The script URL MUST include ?id=TAG_ID for Google Tag Tester detection
|
|
152
|
+
* - dataLayer and the gtag shim are set up BEFORE the script loads
|
|
153
|
+
* - gtag('js') and gtag('config') are called synchronously — they queue
|
|
154
|
+
* into dataLayer and are processed once the real script loads
|
|
155
|
+
* - The returned promise resolves when the script finishes loading
|
|
156
|
+
*/
|
|
157
|
+
private initGtag;
|
|
158
|
+
/**
|
|
159
|
+
* Ensures gtag is initialized exactly once. Subsequent calls return the
|
|
160
|
+
* same promise so the script is never injected twice.
|
|
161
|
+
*/
|
|
162
|
+
private ensureGtag;
|
|
154
163
|
private trackBrowser;
|
|
155
164
|
private identifyBrowser;
|
|
156
165
|
private pageBrowser;
|
|
166
|
+
private buildGtagResult;
|
|
157
167
|
track({ event, properties, userId, anonymousId, timestamp }: TrackOptions): Promise<TrackResult>;
|
|
158
168
|
identify({ userId, traits }: IdentifyOptions): Promise<TrackResult>;
|
|
159
169
|
page({ name, url, referrer, userId, anonymousId }: PageOptions): Promise<TrackResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -126,34 +126,44 @@ declare global {
|
|
|
126
126
|
dataLayer: unknown[];
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
(command: 'config', measurementId: string, config?: GtagConfig): void;
|
|
131
|
-
(command: 'event', eventName: string, params?: Record<string, unknown>): void;
|
|
132
|
-
(command: 'set', config: Record<string, unknown>): void;
|
|
133
|
-
(command: string, ...args: unknown[]): void;
|
|
134
|
-
}
|
|
135
|
-
interface GtagConfig {
|
|
136
|
-
send_page_view?: boolean;
|
|
137
|
-
page_title?: string;
|
|
138
|
-
page_location?: string;
|
|
139
|
-
page_referrer?: string;
|
|
140
|
-
user_id?: string;
|
|
141
|
-
[key: string]: unknown;
|
|
142
|
-
}
|
|
129
|
+
type GtagFn = (...args: unknown[]) => void;
|
|
143
130
|
declare class GoogleAnalyticsProvider extends BaseProvider {
|
|
144
131
|
readonly name = "google-analytics";
|
|
145
132
|
private readonly config;
|
|
146
133
|
private readonly http;
|
|
147
134
|
private readonly endpoint;
|
|
148
135
|
private readonly isBrowser;
|
|
149
|
-
private
|
|
136
|
+
private gtagReady;
|
|
150
137
|
constructor(config: GoogleAnalyticsConfig);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Initializes the gtag.js snippet exactly as Google's official documentation
|
|
140
|
+
* specifies. This mirrors the standard snippet:
|
|
141
|
+
*
|
|
142
|
+
* <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
|
|
143
|
+
* <script>
|
|
144
|
+
* window.dataLayer = window.dataLayer || [];
|
|
145
|
+
* function gtag(){dataLayer.push(arguments);}
|
|
146
|
+
* gtag('js', new Date());
|
|
147
|
+
* gtag('config', 'TAG_ID');
|
|
148
|
+
* </script>
|
|
149
|
+
*
|
|
150
|
+
* Key details:
|
|
151
|
+
* - The script URL MUST include ?id=TAG_ID for Google Tag Tester detection
|
|
152
|
+
* - dataLayer and the gtag shim are set up BEFORE the script loads
|
|
153
|
+
* - gtag('js') and gtag('config') are called synchronously — they queue
|
|
154
|
+
* into dataLayer and are processed once the real script loads
|
|
155
|
+
* - The returned promise resolves when the script finishes loading
|
|
156
|
+
*/
|
|
157
|
+
private initGtag;
|
|
158
|
+
/**
|
|
159
|
+
* Ensures gtag is initialized exactly once. Subsequent calls return the
|
|
160
|
+
* same promise so the script is never injected twice.
|
|
161
|
+
*/
|
|
162
|
+
private ensureGtag;
|
|
154
163
|
private trackBrowser;
|
|
155
164
|
private identifyBrowser;
|
|
156
165
|
private pageBrowser;
|
|
166
|
+
private buildGtagResult;
|
|
157
167
|
track({ event, properties, userId, anonymousId, timestamp }: TrackOptions): Promise<TrackResult>;
|
|
158
168
|
identify({ userId, traits }: IdentifyOptions): Promise<TrackResult>;
|
|
159
169
|
page({ name, url, referrer, userId, anonymousId }: PageOptions): Promise<TrackResult>;
|
package/dist/index.js
CHANGED
|
@@ -82,73 +82,87 @@ function isAxiosError(error) {
|
|
|
82
82
|
// src/providers/google-analytics.ts
|
|
83
83
|
var GA4_ENDPOINT = "https://www.google-analytics.com/mp/collect";
|
|
84
84
|
var GA4_DEBUG_ENDPOINT = "https://www.google-analytics.com/debug/mp/collect";
|
|
85
|
-
var
|
|
85
|
+
var GTAG_SCRIPT_URL = "https://www.googletagmanager.com/gtag/js";
|
|
86
86
|
var GoogleAnalyticsProvider = class extends BaseProvider {
|
|
87
87
|
constructor(config) {
|
|
88
88
|
super();
|
|
89
89
|
this.name = "google-analytics";
|
|
90
|
-
this.
|
|
90
|
+
this.gtagReady = null;
|
|
91
91
|
this.config = config;
|
|
92
92
|
this.http = createHttpClient();
|
|
93
93
|
this.endpoint = config.debug ? GA4_DEBUG_ENDPOINT : GA4_ENDPOINT;
|
|
94
94
|
this.isBrowser = config.appType === "browser";
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Initializes the gtag.js snippet exactly as Google's official documentation
|
|
98
|
+
* specifies. This mirrors the standard snippet:
|
|
99
|
+
*
|
|
100
|
+
* <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
|
|
101
|
+
* <script>
|
|
102
|
+
* window.dataLayer = window.dataLayer || [];
|
|
103
|
+
* function gtag(){dataLayer.push(arguments);}
|
|
104
|
+
* gtag('js', new Date());
|
|
105
|
+
* gtag('config', 'TAG_ID');
|
|
106
|
+
* </script>
|
|
107
|
+
*
|
|
108
|
+
* Key details:
|
|
109
|
+
* - The script URL MUST include ?id=TAG_ID for Google Tag Tester detection
|
|
110
|
+
* - dataLayer and the gtag shim are set up BEFORE the script loads
|
|
111
|
+
* - gtag('js') and gtag('config') are called synchronously — they queue
|
|
112
|
+
* into dataLayer and are processed once the real script loads
|
|
113
|
+
* - The returned promise resolves when the script finishes loading
|
|
114
|
+
*/
|
|
115
|
+
initGtag() {
|
|
116
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
117
|
+
return Promise.resolve();
|
|
102
118
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
119
|
+
window.dataLayer = window.dataLayer || [];
|
|
120
|
+
window.gtag = function gtag() {
|
|
121
|
+
window.dataLayer.push(arguments);
|
|
122
|
+
};
|
|
123
|
+
window.gtag("js", /* @__PURE__ */ new Date());
|
|
124
|
+
window.gtag("config", this.config.measurementId);
|
|
106
125
|
return new Promise((resolve) => {
|
|
107
|
-
window.dataLayer = window.dataLayer || [];
|
|
108
|
-
window.gtag = window.gtag || function gtag(...args) {
|
|
109
|
-
window.dataLayer.push(args);
|
|
110
|
-
};
|
|
111
126
|
const script = document.createElement("script");
|
|
112
127
|
script.async = true;
|
|
113
|
-
script.src = `${
|
|
114
|
-
script.onload = () =>
|
|
115
|
-
window.gtag("js", /* @__PURE__ */ new Date());
|
|
116
|
-
window.gtag("config", this.config.measurementId);
|
|
117
|
-
resolve();
|
|
118
|
-
};
|
|
128
|
+
script.src = `${GTAG_SCRIPT_URL}?id=${this.config.measurementId}`;
|
|
129
|
+
script.onload = () => resolve();
|
|
119
130
|
script.onerror = () => resolve();
|
|
120
|
-
|
|
121
|
-
firstScript.parentNode?.insertBefore(script, firstScript);
|
|
131
|
+
document.head.appendChild(script);
|
|
122
132
|
});
|
|
123
133
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Ensures gtag is initialized exactly once. Subsequent calls return the
|
|
136
|
+
* same promise so the script is never injected twice.
|
|
137
|
+
*/
|
|
138
|
+
ensureGtag() {
|
|
139
|
+
if (!this.gtagReady) {
|
|
140
|
+
this.gtagReady = this.initGtag();
|
|
141
|
+
}
|
|
142
|
+
return this.gtagReady;
|
|
130
143
|
}
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// Browser mode methods — delegate to gtag()
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
131
147
|
async trackBrowser({ event, properties, userId }) {
|
|
132
148
|
if (typeof window === "undefined") {
|
|
133
149
|
return this.buildGtagResult();
|
|
134
150
|
}
|
|
135
|
-
await this.
|
|
151
|
+
await this.ensureGtag();
|
|
136
152
|
if (userId) {
|
|
137
153
|
window.gtag("set", { user_id: userId });
|
|
138
154
|
}
|
|
139
|
-
window.gtag("event", event, properties
|
|
155
|
+
window.gtag("event", event, properties ?? {});
|
|
140
156
|
return this.buildGtagResult();
|
|
141
157
|
}
|
|
142
158
|
async identifyBrowser({ userId, traits }) {
|
|
143
159
|
if (typeof window === "undefined") {
|
|
144
160
|
return this.buildGtagResult();
|
|
145
161
|
}
|
|
146
|
-
await this.
|
|
162
|
+
await this.ensureGtag();
|
|
147
163
|
window.gtag("set", { user_id: userId });
|
|
148
164
|
if (traits) {
|
|
149
|
-
|
|
150
|
-
window.gtag("set", { [key]: value });
|
|
151
|
-
});
|
|
165
|
+
window.gtag("set", "user_properties", traits);
|
|
152
166
|
}
|
|
153
167
|
return this.buildGtagResult();
|
|
154
168
|
}
|
|
@@ -156,31 +170,39 @@ var GoogleAnalyticsProvider = class extends BaseProvider {
|
|
|
156
170
|
if (typeof window === "undefined") {
|
|
157
171
|
return this.buildGtagResult();
|
|
158
172
|
}
|
|
159
|
-
await this.
|
|
160
|
-
const config = {
|
|
161
|
-
page_title: name,
|
|
162
|
-
page_location: url,
|
|
163
|
-
page_referrer: referrer,
|
|
164
|
-
send_page_view: true
|
|
165
|
-
};
|
|
173
|
+
await this.ensureGtag();
|
|
166
174
|
if (userId) {
|
|
167
|
-
|
|
175
|
+
window.gtag("set", { user_id: userId });
|
|
168
176
|
}
|
|
169
|
-
window.gtag("
|
|
177
|
+
window.gtag("event", "page_view", {
|
|
178
|
+
page_title: name,
|
|
179
|
+
page_location: url,
|
|
180
|
+
page_referrer: referrer
|
|
181
|
+
});
|
|
170
182
|
return this.buildGtagResult();
|
|
171
183
|
}
|
|
184
|
+
buildGtagResult() {
|
|
185
|
+
return {
|
|
186
|
+
provider: this.name,
|
|
187
|
+
success: true,
|
|
188
|
+
statusCode: 200
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// Public API — routes to browser or server mode
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
172
194
|
async track({ event, properties, userId, anonymousId, timestamp }) {
|
|
173
195
|
if (this.isBrowser) {
|
|
174
196
|
return this.trackBrowser({ event, properties, userId, anonymousId, timestamp });
|
|
175
197
|
}
|
|
176
198
|
try {
|
|
177
|
-
const
|
|
199
|
+
const clientId = anonymousId ?? this.config.clientId ?? "anonymous";
|
|
178
200
|
const params = { ...properties };
|
|
179
201
|
if (timestamp) {
|
|
180
202
|
params["timestamp_micros"] = timestamp.getTime() * 1e3;
|
|
181
203
|
}
|
|
182
204
|
const body = {
|
|
183
|
-
client_id,
|
|
205
|
+
client_id: clientId,
|
|
184
206
|
events: [{ name: event, params }]
|
|
185
207
|
};
|
|
186
208
|
if (userId) {
|
package/dist/index.mjs
CHANGED
|
@@ -39,73 +39,87 @@ function isAxiosError(error) {
|
|
|
39
39
|
// src/providers/google-analytics.ts
|
|
40
40
|
var GA4_ENDPOINT = "https://www.google-analytics.com/mp/collect";
|
|
41
41
|
var GA4_DEBUG_ENDPOINT = "https://www.google-analytics.com/debug/mp/collect";
|
|
42
|
-
var
|
|
42
|
+
var GTAG_SCRIPT_URL = "https://www.googletagmanager.com/gtag/js";
|
|
43
43
|
var GoogleAnalyticsProvider = class extends BaseProvider {
|
|
44
44
|
constructor(config) {
|
|
45
45
|
super();
|
|
46
46
|
this.name = "google-analytics";
|
|
47
|
-
this.
|
|
47
|
+
this.gtagReady = null;
|
|
48
48
|
this.config = config;
|
|
49
49
|
this.http = createHttpClient();
|
|
50
50
|
this.endpoint = config.debug ? GA4_DEBUG_ENDPOINT : GA4_ENDPOINT;
|
|
51
51
|
this.isBrowser = config.appType === "browser";
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Initializes the gtag.js snippet exactly as Google's official documentation
|
|
55
|
+
* specifies. This mirrors the standard snippet:
|
|
56
|
+
*
|
|
57
|
+
* <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
|
|
58
|
+
* <script>
|
|
59
|
+
* window.dataLayer = window.dataLayer || [];
|
|
60
|
+
* function gtag(){dataLayer.push(arguments);}
|
|
61
|
+
* gtag('js', new Date());
|
|
62
|
+
* gtag('config', 'TAG_ID');
|
|
63
|
+
* </script>
|
|
64
|
+
*
|
|
65
|
+
* Key details:
|
|
66
|
+
* - The script URL MUST include ?id=TAG_ID for Google Tag Tester detection
|
|
67
|
+
* - dataLayer and the gtag shim are set up BEFORE the script loads
|
|
68
|
+
* - gtag('js') and gtag('config') are called synchronously — they queue
|
|
69
|
+
* into dataLayer and are processed once the real script loads
|
|
70
|
+
* - The returned promise resolves when the script finishes loading
|
|
71
|
+
*/
|
|
72
|
+
initGtag() {
|
|
73
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
74
|
+
return Promise.resolve();
|
|
59
75
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
window.dataLayer = window.dataLayer || [];
|
|
77
|
+
window.gtag = function gtag() {
|
|
78
|
+
window.dataLayer.push(arguments);
|
|
79
|
+
};
|
|
80
|
+
window.gtag("js", /* @__PURE__ */ new Date());
|
|
81
|
+
window.gtag("config", this.config.measurementId);
|
|
63
82
|
return new Promise((resolve) => {
|
|
64
|
-
window.dataLayer = window.dataLayer || [];
|
|
65
|
-
window.gtag = window.gtag || function gtag(...args) {
|
|
66
|
-
window.dataLayer.push(args);
|
|
67
|
-
};
|
|
68
83
|
const script = document.createElement("script");
|
|
69
84
|
script.async = true;
|
|
70
|
-
script.src = `${
|
|
71
|
-
script.onload = () =>
|
|
72
|
-
window.gtag("js", /* @__PURE__ */ new Date());
|
|
73
|
-
window.gtag("config", this.config.measurementId);
|
|
74
|
-
resolve();
|
|
75
|
-
};
|
|
85
|
+
script.src = `${GTAG_SCRIPT_URL}?id=${this.config.measurementId}`;
|
|
86
|
+
script.onload = () => resolve();
|
|
76
87
|
script.onerror = () => resolve();
|
|
77
|
-
|
|
78
|
-
firstScript.parentNode?.insertBefore(script, firstScript);
|
|
88
|
+
document.head.appendChild(script);
|
|
79
89
|
});
|
|
80
90
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Ensures gtag is initialized exactly once. Subsequent calls return the
|
|
93
|
+
* same promise so the script is never injected twice.
|
|
94
|
+
*/
|
|
95
|
+
ensureGtag() {
|
|
96
|
+
if (!this.gtagReady) {
|
|
97
|
+
this.gtagReady = this.initGtag();
|
|
98
|
+
}
|
|
99
|
+
return this.gtagReady;
|
|
87
100
|
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Browser mode methods — delegate to gtag()
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
88
104
|
async trackBrowser({ event, properties, userId }) {
|
|
89
105
|
if (typeof window === "undefined") {
|
|
90
106
|
return this.buildGtagResult();
|
|
91
107
|
}
|
|
92
|
-
await this.
|
|
108
|
+
await this.ensureGtag();
|
|
93
109
|
if (userId) {
|
|
94
110
|
window.gtag("set", { user_id: userId });
|
|
95
111
|
}
|
|
96
|
-
window.gtag("event", event, properties
|
|
112
|
+
window.gtag("event", event, properties ?? {});
|
|
97
113
|
return this.buildGtagResult();
|
|
98
114
|
}
|
|
99
115
|
async identifyBrowser({ userId, traits }) {
|
|
100
116
|
if (typeof window === "undefined") {
|
|
101
117
|
return this.buildGtagResult();
|
|
102
118
|
}
|
|
103
|
-
await this.
|
|
119
|
+
await this.ensureGtag();
|
|
104
120
|
window.gtag("set", { user_id: userId });
|
|
105
121
|
if (traits) {
|
|
106
|
-
|
|
107
|
-
window.gtag("set", { [key]: value });
|
|
108
|
-
});
|
|
122
|
+
window.gtag("set", "user_properties", traits);
|
|
109
123
|
}
|
|
110
124
|
return this.buildGtagResult();
|
|
111
125
|
}
|
|
@@ -113,31 +127,39 @@ var GoogleAnalyticsProvider = class extends BaseProvider {
|
|
|
113
127
|
if (typeof window === "undefined") {
|
|
114
128
|
return this.buildGtagResult();
|
|
115
129
|
}
|
|
116
|
-
await this.
|
|
117
|
-
const config = {
|
|
118
|
-
page_title: name,
|
|
119
|
-
page_location: url,
|
|
120
|
-
page_referrer: referrer,
|
|
121
|
-
send_page_view: true
|
|
122
|
-
};
|
|
130
|
+
await this.ensureGtag();
|
|
123
131
|
if (userId) {
|
|
124
|
-
|
|
132
|
+
window.gtag("set", { user_id: userId });
|
|
125
133
|
}
|
|
126
|
-
window.gtag("
|
|
134
|
+
window.gtag("event", "page_view", {
|
|
135
|
+
page_title: name,
|
|
136
|
+
page_location: url,
|
|
137
|
+
page_referrer: referrer
|
|
138
|
+
});
|
|
127
139
|
return this.buildGtagResult();
|
|
128
140
|
}
|
|
141
|
+
buildGtagResult() {
|
|
142
|
+
return {
|
|
143
|
+
provider: this.name,
|
|
144
|
+
success: true,
|
|
145
|
+
statusCode: 200
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// Public API — routes to browser or server mode
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
129
151
|
async track({ event, properties, userId, anonymousId, timestamp }) {
|
|
130
152
|
if (this.isBrowser) {
|
|
131
153
|
return this.trackBrowser({ event, properties, userId, anonymousId, timestamp });
|
|
132
154
|
}
|
|
133
155
|
try {
|
|
134
|
-
const
|
|
156
|
+
const clientId = anonymousId ?? this.config.clientId ?? "anonymous";
|
|
135
157
|
const params = { ...properties };
|
|
136
158
|
if (timestamp) {
|
|
137
159
|
params["timestamp_micros"] = timestamp.getTime() * 1e3;
|
|
138
160
|
}
|
|
139
161
|
const body = {
|
|
140
|
-
client_id,
|
|
162
|
+
client_id: clientId,
|
|
141
163
|
events: [{ name: event, params }]
|
|
142
164
|
};
|
|
143
165
|
if (userId) {
|