@nextlytics/core 0.1.0-canary-1
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/dist/anonymous-user.cjs +118 -0
- package/dist/anonymous-user.d.mts +22 -0
- package/dist/anonymous-user.d.ts +22 -0
- package/dist/anonymous-user.js +94 -0
- package/dist/backends/clickhouse.cjs +110 -0
- package/dist/backends/clickhouse.d.mts +58 -0
- package/dist/backends/clickhouse.d.ts +58 -0
- package/dist/backends/clickhouse.js +92 -0
- package/dist/backends/ga.cjs +207 -0
- package/dist/backends/ga.d.mts +21 -0
- package/dist/backends/ga.d.ts +21 -0
- package/dist/backends/ga.js +183 -0
- package/dist/backends/gtm.cjs +155 -0
- package/dist/backends/gtm.d.mts +11 -0
- package/dist/backends/gtm.d.ts +11 -0
- package/dist/backends/gtm.js +131 -0
- package/dist/backends/lib/db.cjs +150 -0
- package/dist/backends/lib/db.d.mts +121 -0
- package/dist/backends/lib/db.d.ts +121 -0
- package/dist/backends/lib/db.js +119 -0
- package/dist/backends/logging.cjs +45 -0
- package/dist/backends/logging.d.mts +7 -0
- package/dist/backends/logging.d.ts +7 -0
- package/dist/backends/logging.js +21 -0
- package/dist/backends/neon.cjs +84 -0
- package/dist/backends/neon.d.mts +11 -0
- package/dist/backends/neon.d.ts +11 -0
- package/dist/backends/neon.js +66 -0
- package/dist/backends/postgrest.cjs +98 -0
- package/dist/backends/postgrest.d.mts +46 -0
- package/dist/backends/postgrest.d.ts +46 -0
- package/dist/backends/postgrest.js +73 -0
- package/dist/backends/posthog.cjs +120 -0
- package/dist/backends/posthog.d.mts +13 -0
- package/dist/backends/posthog.d.ts +13 -0
- package/dist/backends/posthog.js +96 -0
- package/dist/backends/segment.cjs +112 -0
- package/dist/backends/segment.d.mts +43 -0
- package/dist/backends/segment.d.ts +43 -0
- package/dist/backends/segment.js +88 -0
- package/dist/client.cjs +171 -0
- package/dist/client.d.mts +29 -0
- package/dist/client.d.ts +29 -0
- package/dist/client.js +146 -0
- package/dist/config-helpers.cjs +71 -0
- package/dist/config-helpers.d.mts +16 -0
- package/dist/config-helpers.d.ts +16 -0
- package/dist/config-helpers.js +45 -0
- package/dist/handlers.cjs +123 -0
- package/dist/handlers.d.mts +9 -0
- package/dist/handlers.d.ts +9 -0
- package/dist/handlers.js +99 -0
- package/dist/headers.cjs +41 -0
- package/dist/headers.d.mts +3 -0
- package/dist/headers.d.ts +3 -0
- package/dist/headers.js +17 -0
- package/dist/index.cjs +41 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +12 -0
- package/dist/middleware.cjs +204 -0
- package/dist/middleware.d.mts +10 -0
- package/dist/middleware.d.ts +10 -0
- package/dist/middleware.js +183 -0
- package/dist/pages-router.cjs +45 -0
- package/dist/pages-router.d.mts +45 -0
- package/dist/pages-router.d.ts +45 -0
- package/dist/pages-router.js +21 -0
- package/dist/plugins/vercel-geo.cjs +60 -0
- package/dist/plugins/vercel-geo.d.mts +25 -0
- package/dist/plugins/vercel-geo.d.ts +25 -0
- package/dist/plugins/vercel-geo.js +36 -0
- package/dist/server-component-context.cjs +95 -0
- package/dist/server-component-context.d.mts +30 -0
- package/dist/server-component-context.d.ts +30 -0
- package/dist/server-component-context.js +69 -0
- package/dist/server.cjs +236 -0
- package/dist/server.d.mts +13 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +213 -0
- package/dist/template.cjs +108 -0
- package/dist/template.d.mts +27 -0
- package/dist/template.d.ts +27 -0
- package/dist/template.js +83 -0
- package/dist/types.cjs +16 -0
- package/dist/types.d.mts +216 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.js +0 -0
- package/dist/uitils.cjs +94 -0
- package/dist/uitils.d.mts +22 -0
- package/dist/uitils.d.ts +22 -0
- package/dist/uitils.js +68 -0
- package/package.json +162 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var ga_exports = {};
|
|
20
|
+
__export(ga_exports, {
|
|
21
|
+
googleAnalyticsBackend: () => googleAnalyticsBackend
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(ga_exports);
|
|
24
|
+
const GA_TEMPLATE_ID = "ga-gtag";
|
|
25
|
+
function parseGaCookie(cookieValue) {
|
|
26
|
+
const match = cookieValue.match(/^GA\d+\.\d+\.(.+)$/);
|
|
27
|
+
return match ? match[1] : null;
|
|
28
|
+
}
|
|
29
|
+
function getClientId(event, gaCookieClientId, source) {
|
|
30
|
+
if (source === "gaCookie" && gaCookieClientId) {
|
|
31
|
+
return gaCookieClientId;
|
|
32
|
+
}
|
|
33
|
+
if (!event.anonymousUserId) {
|
|
34
|
+
throw new Error("anonymousUserId is required for GA backend (no _ga cookie available)");
|
|
35
|
+
}
|
|
36
|
+
return event.anonymousUserId;
|
|
37
|
+
}
|
|
38
|
+
function toGA4EventName(type) {
|
|
39
|
+
if (type === "pageView") return "page_view";
|
|
40
|
+
if (type === "apiCall") return "api_call";
|
|
41
|
+
return type.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
42
|
+
}
|
|
43
|
+
function buildEventParams(event) {
|
|
44
|
+
const params = {
|
|
45
|
+
// Required for engagement metrics
|
|
46
|
+
engagement_time_msec: 1
|
|
47
|
+
};
|
|
48
|
+
const { serverContext } = event;
|
|
49
|
+
if (serverContext) {
|
|
50
|
+
params.page_location = `https://${serverContext.host}${serverContext.path}`;
|
|
51
|
+
}
|
|
52
|
+
const { clientContext } = event;
|
|
53
|
+
if (clientContext) {
|
|
54
|
+
if (clientContext.referer) {
|
|
55
|
+
params.page_referrer = clientContext.referer;
|
|
56
|
+
}
|
|
57
|
+
if (clientContext.locale) {
|
|
58
|
+
params.language = clientContext.locale;
|
|
59
|
+
}
|
|
60
|
+
if (clientContext.screen?.width && clientContext.screen?.height) {
|
|
61
|
+
params.screen_resolution = `${clientContext.screen.width}x${clientContext.screen.height}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (event.properties) {
|
|
65
|
+
Object.assign(params, event.properties);
|
|
66
|
+
}
|
|
67
|
+
return params;
|
|
68
|
+
}
|
|
69
|
+
function getUserAgent(event) {
|
|
70
|
+
return event.clientContext?.userAgent ?? event.serverContext?.requestHeaders?.["user-agent"];
|
|
71
|
+
}
|
|
72
|
+
function getClientIp(event) {
|
|
73
|
+
return event.serverContext?.ip;
|
|
74
|
+
}
|
|
75
|
+
async function sendToMeasurementProtocol(opts) {
|
|
76
|
+
const endpoint = opts.debugMode ? "https://www.google-analytics.com/debug/mp/collect" : "https://www.google-analytics.com/mp/collect";
|
|
77
|
+
const url = `${endpoint}?measurement_id=${opts.measurementId}&api_secret=${opts.apiSecret}`;
|
|
78
|
+
const payload = {
|
|
79
|
+
client_id: opts.clientId,
|
|
80
|
+
events: [
|
|
81
|
+
{
|
|
82
|
+
name: opts.eventName,
|
|
83
|
+
params: opts.eventParams
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
};
|
|
87
|
+
if (opts.userId) {
|
|
88
|
+
payload.user_id = opts.userId;
|
|
89
|
+
}
|
|
90
|
+
if (opts.userProperties && Object.keys(opts.userProperties).length > 0) {
|
|
91
|
+
payload.user_properties = Object.fromEntries(
|
|
92
|
+
Object.entries(opts.userProperties).map(([k, v]) => [k, { value: v }])
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const headers = {};
|
|
96
|
+
if (opts.userAgent) {
|
|
97
|
+
headers["User-Agent"] = opts.userAgent;
|
|
98
|
+
}
|
|
99
|
+
if (opts.clientIp) {
|
|
100
|
+
headers["X-Forwarded-For"] = opts.clientIp;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const res = await fetch(url, {
|
|
104
|
+
method: "POST",
|
|
105
|
+
body: JSON.stringify(payload),
|
|
106
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const body = await res.text().catch(() => "");
|
|
110
|
+
console.warn(`[GA] Measurement Protocol error: ${res.status} ${res.statusText}`, body);
|
|
111
|
+
}
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.warn("[GA] Measurement Protocol request failed:", err);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function googleAnalyticsBackend(opts) {
|
|
117
|
+
const { measurementId, debugMode, apiSecret, clientIdSource = "gaCookie" } = opts;
|
|
118
|
+
return (ctx) => {
|
|
119
|
+
const gaCookie = ctx.cookies.get("_ga");
|
|
120
|
+
const gaCookieClientId = gaCookie ? parseGaCookie(gaCookie.value) : null;
|
|
121
|
+
return {
|
|
122
|
+
name: "google-analytics",
|
|
123
|
+
returnsClientActions: true,
|
|
124
|
+
supportsUpdates: false,
|
|
125
|
+
getClientSideTemplates() {
|
|
126
|
+
return {
|
|
127
|
+
[GA_TEMPLATE_ID]: {
|
|
128
|
+
items: [
|
|
129
|
+
{
|
|
130
|
+
async: "true",
|
|
131
|
+
src: "https://www.googletagmanager.com/gtag/js?id={{measurementId}}",
|
|
132
|
+
singleton: true
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
body: [
|
|
136
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
137
|
+
"function gtag(){dataLayer.push(arguments);}",
|
|
138
|
+
"gtag('js', new Date());",
|
|
139
|
+
"gtag('config', '{{measurementId}}', {{json(config)}});",
|
|
140
|
+
"gtag('event', 'page_view');"
|
|
141
|
+
].join("\n")
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
async onEvent(event) {
|
|
148
|
+
const clientId = getClientId(event, gaCookieClientId, clientIdSource);
|
|
149
|
+
const userId = event.userContext?.userId;
|
|
150
|
+
const {
|
|
151
|
+
email: _email,
|
|
152
|
+
name: _name,
|
|
153
|
+
phone: _phone,
|
|
154
|
+
...customTraits
|
|
155
|
+
} = event.userContext?.traits ?? {};
|
|
156
|
+
const userProperties = Object.keys(customTraits).length > 0 ? customTraits : void 0;
|
|
157
|
+
if (event.type === "pageView") {
|
|
158
|
+
const config = {
|
|
159
|
+
send_page_view: false,
|
|
160
|
+
client_id: clientId
|
|
161
|
+
};
|
|
162
|
+
if (debugMode) {
|
|
163
|
+
config.debug_mode = true;
|
|
164
|
+
}
|
|
165
|
+
if (userId) {
|
|
166
|
+
config.user_id = userId;
|
|
167
|
+
}
|
|
168
|
+
if (userProperties) {
|
|
169
|
+
config.user_properties = userProperties;
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
items: [
|
|
173
|
+
{
|
|
174
|
+
type: "script-template",
|
|
175
|
+
templateId: GA_TEMPLATE_ID,
|
|
176
|
+
params: {
|
|
177
|
+
measurementId,
|
|
178
|
+
config
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (apiSecret) {
|
|
185
|
+
await sendToMeasurementProtocol({
|
|
186
|
+
measurementId,
|
|
187
|
+
apiSecret,
|
|
188
|
+
clientId,
|
|
189
|
+
userId,
|
|
190
|
+
userProperties,
|
|
191
|
+
eventName: toGA4EventName(event.type),
|
|
192
|
+
eventParams: buildEventParams(event),
|
|
193
|
+
userAgent: getUserAgent(event),
|
|
194
|
+
clientIp: getClientIp(event),
|
|
195
|
+
debugMode
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
updateEvent() {
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
205
|
+
0 && (module.exports = {
|
|
206
|
+
googleAnalyticsBackend
|
|
207
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NextlyticsBackendFactory } from '../types.mjs';
|
|
2
|
+
import 'next/dist/server/web/spec-extension/cookies';
|
|
3
|
+
import 'next/server';
|
|
4
|
+
|
|
5
|
+
type GoogleAnalyticsBackendOptions = {
|
|
6
|
+
/** GA4 Measurement ID (e.g. "G-XXXXXXXXXX") */
|
|
7
|
+
measurementId: string;
|
|
8
|
+
/** Enable GA4 debug mode (shows events in DebugView) */
|
|
9
|
+
debugMode?: boolean;
|
|
10
|
+
/** API secret for Measurement Protocol (GA4 Admin → Data Streams → MP secrets) */
|
|
11
|
+
apiSecret?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Source for client_id.
|
|
14
|
+
* - "gaCookie" (default): Use _ga cookie set by gtag.js, fall back to anonymousUserId
|
|
15
|
+
* - "anonymousUserId": Always use Nextlytics anonymousUserId
|
|
16
|
+
*/
|
|
17
|
+
clientIdSource?: "gaCookie" | "anonymousUserId";
|
|
18
|
+
};
|
|
19
|
+
declare function googleAnalyticsBackend(opts: GoogleAnalyticsBackendOptions): NextlyticsBackendFactory;
|
|
20
|
+
|
|
21
|
+
export { type GoogleAnalyticsBackendOptions, googleAnalyticsBackend };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NextlyticsBackendFactory } from '../types.js';
|
|
2
|
+
import 'next/dist/server/web/spec-extension/cookies';
|
|
3
|
+
import 'next/server';
|
|
4
|
+
|
|
5
|
+
type GoogleAnalyticsBackendOptions = {
|
|
6
|
+
/** GA4 Measurement ID (e.g. "G-XXXXXXXXXX") */
|
|
7
|
+
measurementId: string;
|
|
8
|
+
/** Enable GA4 debug mode (shows events in DebugView) */
|
|
9
|
+
debugMode?: boolean;
|
|
10
|
+
/** API secret for Measurement Protocol (GA4 Admin → Data Streams → MP secrets) */
|
|
11
|
+
apiSecret?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Source for client_id.
|
|
14
|
+
* - "gaCookie" (default): Use _ga cookie set by gtag.js, fall back to anonymousUserId
|
|
15
|
+
* - "anonymousUserId": Always use Nextlytics anonymousUserId
|
|
16
|
+
*/
|
|
17
|
+
clientIdSource?: "gaCookie" | "anonymousUserId";
|
|
18
|
+
};
|
|
19
|
+
declare function googleAnalyticsBackend(opts: GoogleAnalyticsBackendOptions): NextlyticsBackendFactory;
|
|
20
|
+
|
|
21
|
+
export { type GoogleAnalyticsBackendOptions, googleAnalyticsBackend };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const GA_TEMPLATE_ID = "ga-gtag";
|
|
2
|
+
function parseGaCookie(cookieValue) {
|
|
3
|
+
const match = cookieValue.match(/^GA\d+\.\d+\.(.+)$/);
|
|
4
|
+
return match ? match[1] : null;
|
|
5
|
+
}
|
|
6
|
+
function getClientId(event, gaCookieClientId, source) {
|
|
7
|
+
if (source === "gaCookie" && gaCookieClientId) {
|
|
8
|
+
return gaCookieClientId;
|
|
9
|
+
}
|
|
10
|
+
if (!event.anonymousUserId) {
|
|
11
|
+
throw new Error("anonymousUserId is required for GA backend (no _ga cookie available)");
|
|
12
|
+
}
|
|
13
|
+
return event.anonymousUserId;
|
|
14
|
+
}
|
|
15
|
+
function toGA4EventName(type) {
|
|
16
|
+
if (type === "pageView") return "page_view";
|
|
17
|
+
if (type === "apiCall") return "api_call";
|
|
18
|
+
return type.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
19
|
+
}
|
|
20
|
+
function buildEventParams(event) {
|
|
21
|
+
const params = {
|
|
22
|
+
// Required for engagement metrics
|
|
23
|
+
engagement_time_msec: 1
|
|
24
|
+
};
|
|
25
|
+
const { serverContext } = event;
|
|
26
|
+
if (serverContext) {
|
|
27
|
+
params.page_location = `https://${serverContext.host}${serverContext.path}`;
|
|
28
|
+
}
|
|
29
|
+
const { clientContext } = event;
|
|
30
|
+
if (clientContext) {
|
|
31
|
+
if (clientContext.referer) {
|
|
32
|
+
params.page_referrer = clientContext.referer;
|
|
33
|
+
}
|
|
34
|
+
if (clientContext.locale) {
|
|
35
|
+
params.language = clientContext.locale;
|
|
36
|
+
}
|
|
37
|
+
if (clientContext.screen?.width && clientContext.screen?.height) {
|
|
38
|
+
params.screen_resolution = `${clientContext.screen.width}x${clientContext.screen.height}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (event.properties) {
|
|
42
|
+
Object.assign(params, event.properties);
|
|
43
|
+
}
|
|
44
|
+
return params;
|
|
45
|
+
}
|
|
46
|
+
function getUserAgent(event) {
|
|
47
|
+
return event.clientContext?.userAgent ?? event.serverContext?.requestHeaders?.["user-agent"];
|
|
48
|
+
}
|
|
49
|
+
function getClientIp(event) {
|
|
50
|
+
return event.serverContext?.ip;
|
|
51
|
+
}
|
|
52
|
+
async function sendToMeasurementProtocol(opts) {
|
|
53
|
+
const endpoint = opts.debugMode ? "https://www.google-analytics.com/debug/mp/collect" : "https://www.google-analytics.com/mp/collect";
|
|
54
|
+
const url = `${endpoint}?measurement_id=${opts.measurementId}&api_secret=${opts.apiSecret}`;
|
|
55
|
+
const payload = {
|
|
56
|
+
client_id: opts.clientId,
|
|
57
|
+
events: [
|
|
58
|
+
{
|
|
59
|
+
name: opts.eventName,
|
|
60
|
+
params: opts.eventParams
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
};
|
|
64
|
+
if (opts.userId) {
|
|
65
|
+
payload.user_id = opts.userId;
|
|
66
|
+
}
|
|
67
|
+
if (opts.userProperties && Object.keys(opts.userProperties).length > 0) {
|
|
68
|
+
payload.user_properties = Object.fromEntries(
|
|
69
|
+
Object.entries(opts.userProperties).map(([k, v]) => [k, { value: v }])
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
const headers = {};
|
|
73
|
+
if (opts.userAgent) {
|
|
74
|
+
headers["User-Agent"] = opts.userAgent;
|
|
75
|
+
}
|
|
76
|
+
if (opts.clientIp) {
|
|
77
|
+
headers["X-Forwarded-For"] = opts.clientIp;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const res = await fetch(url, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
body: JSON.stringify(payload),
|
|
83
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0
|
|
84
|
+
});
|
|
85
|
+
if (!res.ok) {
|
|
86
|
+
const body = await res.text().catch(() => "");
|
|
87
|
+
console.warn(`[GA] Measurement Protocol error: ${res.status} ${res.statusText}`, body);
|
|
88
|
+
}
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.warn("[GA] Measurement Protocol request failed:", err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function googleAnalyticsBackend(opts) {
|
|
94
|
+
const { measurementId, debugMode, apiSecret, clientIdSource = "gaCookie" } = opts;
|
|
95
|
+
return (ctx) => {
|
|
96
|
+
const gaCookie = ctx.cookies.get("_ga");
|
|
97
|
+
const gaCookieClientId = gaCookie ? parseGaCookie(gaCookie.value) : null;
|
|
98
|
+
return {
|
|
99
|
+
name: "google-analytics",
|
|
100
|
+
returnsClientActions: true,
|
|
101
|
+
supportsUpdates: false,
|
|
102
|
+
getClientSideTemplates() {
|
|
103
|
+
return {
|
|
104
|
+
[GA_TEMPLATE_ID]: {
|
|
105
|
+
items: [
|
|
106
|
+
{
|
|
107
|
+
async: "true",
|
|
108
|
+
src: "https://www.googletagmanager.com/gtag/js?id={{measurementId}}",
|
|
109
|
+
singleton: true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
body: [
|
|
113
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
114
|
+
"function gtag(){dataLayer.push(arguments);}",
|
|
115
|
+
"gtag('js', new Date());",
|
|
116
|
+
"gtag('config', '{{measurementId}}', {{json(config)}});",
|
|
117
|
+
"gtag('event', 'page_view');"
|
|
118
|
+
].join("\n")
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
async onEvent(event) {
|
|
125
|
+
const clientId = getClientId(event, gaCookieClientId, clientIdSource);
|
|
126
|
+
const userId = event.userContext?.userId;
|
|
127
|
+
const {
|
|
128
|
+
email: _email,
|
|
129
|
+
name: _name,
|
|
130
|
+
phone: _phone,
|
|
131
|
+
...customTraits
|
|
132
|
+
} = event.userContext?.traits ?? {};
|
|
133
|
+
const userProperties = Object.keys(customTraits).length > 0 ? customTraits : void 0;
|
|
134
|
+
if (event.type === "pageView") {
|
|
135
|
+
const config = {
|
|
136
|
+
send_page_view: false,
|
|
137
|
+
client_id: clientId
|
|
138
|
+
};
|
|
139
|
+
if (debugMode) {
|
|
140
|
+
config.debug_mode = true;
|
|
141
|
+
}
|
|
142
|
+
if (userId) {
|
|
143
|
+
config.user_id = userId;
|
|
144
|
+
}
|
|
145
|
+
if (userProperties) {
|
|
146
|
+
config.user_properties = userProperties;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
items: [
|
|
150
|
+
{
|
|
151
|
+
type: "script-template",
|
|
152
|
+
templateId: GA_TEMPLATE_ID,
|
|
153
|
+
params: {
|
|
154
|
+
measurementId,
|
|
155
|
+
config
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (apiSecret) {
|
|
162
|
+
await sendToMeasurementProtocol({
|
|
163
|
+
measurementId,
|
|
164
|
+
apiSecret,
|
|
165
|
+
clientId,
|
|
166
|
+
userId,
|
|
167
|
+
userProperties,
|
|
168
|
+
eventName: toGA4EventName(event.type),
|
|
169
|
+
eventParams: buildEventParams(event),
|
|
170
|
+
userAgent: getUserAgent(event),
|
|
171
|
+
clientIp: getClientIp(event),
|
|
172
|
+
debugMode
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
updateEvent() {
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
export {
|
|
182
|
+
googleAnalyticsBackend
|
|
183
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var gtm_exports = {};
|
|
20
|
+
__export(gtm_exports, {
|
|
21
|
+
googleTagManagerBackend: () => googleTagManagerBackend
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(gtm_exports);
|
|
24
|
+
const GTM_INIT_TEMPLATE_ID = "gtm-init";
|
|
25
|
+
const GTM_PAGEVIEW_TEMPLATE_ID = "gtm-pageview";
|
|
26
|
+
const GTM_EVENT_TEMPLATE_ID = "gtm-event";
|
|
27
|
+
function toSnakeCase(str) {
|
|
28
|
+
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
29
|
+
}
|
|
30
|
+
function googleTagManagerBackend(opts) {
|
|
31
|
+
const { containerId } = opts;
|
|
32
|
+
return {
|
|
33
|
+
name: "google-tag-manager",
|
|
34
|
+
returnsClientActions: true,
|
|
35
|
+
supportsUpdates: false,
|
|
36
|
+
getClientSideTemplates() {
|
|
37
|
+
return {
|
|
38
|
+
[GTM_INIT_TEMPLATE_ID]: {
|
|
39
|
+
items: [
|
|
40
|
+
{
|
|
41
|
+
body: [
|
|
42
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
43
|
+
"dataLayer.push({{json(initialData)}});",
|
|
44
|
+
"if (!window.google_tag_manager || !window.google_tag_manager['{{containerId}}']) {",
|
|
45
|
+
" (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':",
|
|
46
|
+
" new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],",
|
|
47
|
+
" j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=",
|
|
48
|
+
" 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);",
|
|
49
|
+
" })(window,document,'script','dataLayer','{{containerId}}');",
|
|
50
|
+
"}"
|
|
51
|
+
].join("\n")
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
[GTM_PAGEVIEW_TEMPLATE_ID]: {
|
|
56
|
+
items: [
|
|
57
|
+
{
|
|
58
|
+
body: [
|
|
59
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
60
|
+
"dataLayer.push({{json(pageData)}});"
|
|
61
|
+
].join("\n")
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
[GTM_EVENT_TEMPLATE_ID]: {
|
|
66
|
+
items: [
|
|
67
|
+
{
|
|
68
|
+
body: [
|
|
69
|
+
"window.dataLayer = window.dataLayer || [];",
|
|
70
|
+
"dataLayer.push({{json(eventData)}});"
|
|
71
|
+
].join("\n")
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
async onEvent(event) {
|
|
78
|
+
if (event.type !== "pageView") {
|
|
79
|
+
const eventData = {
|
|
80
|
+
event: toSnakeCase(event.type),
|
|
81
|
+
eventId: event.eventId,
|
|
82
|
+
...event.properties
|
|
83
|
+
};
|
|
84
|
+
if (event.userContext?.userId) {
|
|
85
|
+
eventData.userId = event.userContext.userId;
|
|
86
|
+
}
|
|
87
|
+
if (event.anonymousUserId) {
|
|
88
|
+
eventData.anonymousUserId = event.anonymousUserId;
|
|
89
|
+
}
|
|
90
|
+
const traits2 = event.userContext?.traits;
|
|
91
|
+
if (traits2 && Object.keys(traits2).length > 0) {
|
|
92
|
+
eventData.userTraits = traits2;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
items: [
|
|
96
|
+
{
|
|
97
|
+
type: "script-template",
|
|
98
|
+
templateId: GTM_EVENT_TEMPLATE_ID,
|
|
99
|
+
params: { eventData }
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const initialData = {};
|
|
105
|
+
if (event.userContext?.userId) {
|
|
106
|
+
initialData.userId = event.userContext.userId;
|
|
107
|
+
}
|
|
108
|
+
if (event.anonymousUserId) {
|
|
109
|
+
initialData.anonymousUserId = event.anonymousUserId;
|
|
110
|
+
}
|
|
111
|
+
const traits = event.userContext?.traits;
|
|
112
|
+
if (traits && Object.keys(traits).length > 0) {
|
|
113
|
+
initialData.userTraits = traits;
|
|
114
|
+
}
|
|
115
|
+
const pageData = {
|
|
116
|
+
event: "page_view",
|
|
117
|
+
eventId: event.eventId,
|
|
118
|
+
page_path: event.serverContext.path,
|
|
119
|
+
page_title: event.properties.title ?? void 0,
|
|
120
|
+
page_location: `${event.serverContext.host}${event.serverContext.path}`
|
|
121
|
+
};
|
|
122
|
+
if (event.clientContext) {
|
|
123
|
+
return {
|
|
124
|
+
items: [
|
|
125
|
+
{
|
|
126
|
+
type: "script-template",
|
|
127
|
+
templateId: GTM_PAGEVIEW_TEMPLATE_ID,
|
|
128
|
+
params: { pageData }
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
items: [
|
|
135
|
+
{
|
|
136
|
+
type: "script-template",
|
|
137
|
+
templateId: GTM_INIT_TEMPLATE_ID,
|
|
138
|
+
params: { containerId, initialData }
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: "script-template",
|
|
142
|
+
templateId: GTM_PAGEVIEW_TEMPLATE_ID,
|
|
143
|
+
params: { pageData }
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
updateEvent() {
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
153
|
+
0 && (module.exports = {
|
|
154
|
+
googleTagManagerBackend
|
|
155
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextlyticsBackend } from '../types.mjs';
|
|
2
|
+
import 'next/dist/server/web/spec-extension/cookies';
|
|
3
|
+
import 'next/server';
|
|
4
|
+
|
|
5
|
+
type GoogleTagManagerBackendOptions = {
|
|
6
|
+
/** GTM Container ID (e.g. "GTM-XXXXXXX") */
|
|
7
|
+
containerId: string;
|
|
8
|
+
};
|
|
9
|
+
declare function googleTagManagerBackend(opts: GoogleTagManagerBackendOptions): NextlyticsBackend;
|
|
10
|
+
|
|
11
|
+
export { type GoogleTagManagerBackendOptions, googleTagManagerBackend };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextlyticsBackend } from '../types.js';
|
|
2
|
+
import 'next/dist/server/web/spec-extension/cookies';
|
|
3
|
+
import 'next/server';
|
|
4
|
+
|
|
5
|
+
type GoogleTagManagerBackendOptions = {
|
|
6
|
+
/** GTM Container ID (e.g. "GTM-XXXXXXX") */
|
|
7
|
+
containerId: string;
|
|
8
|
+
};
|
|
9
|
+
declare function googleTagManagerBackend(opts: GoogleTagManagerBackendOptions): NextlyticsBackend;
|
|
10
|
+
|
|
11
|
+
export { type GoogleTagManagerBackendOptions, googleTagManagerBackend };
|