@jitsu/js 1.1.0 → 1.1.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/.turbo/turbo-build.log +65 -65
- package/.turbo/turbo-clean.log +5 -5
- package/__tests__/node/nodejs.test.ts +15 -4
- package/__tests__/playwright/integration.test.ts +1 -2
- package/dist/analytics-plugin.d.ts +1 -0
- package/dist/destination-plugins.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/jitsu.cjs.js +157 -54
- package/dist/jitsu.es.js +157 -54
- package/dist/version.d.ts +2 -0
- package/dist/web/p.js.txt +156 -54
- package/package.json +3 -3
- package/src/analytics-plugin.ts +50 -17
- package/src/destination-plugins/gtm.ts +112 -0
- package/src/destination-plugins/index.ts +47 -0
- package/src/destination-plugins/logrocket.ts +83 -0
- package/src/{destination-plugins.ts → destination-plugins/tag.ts} +3 -28
- package/src/index.ts +13 -3
- package/src/version.ts +3 -0
- package/tsconfig.json +1 -0
package/src/analytics-plugin.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/* global analytics */
|
|
2
2
|
|
|
3
3
|
import { JitsuOptions, PersistentStorage, RuntimeFacade } from "./jitsu";
|
|
4
|
-
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
4
|
+
import { AnalyticsClientEvent, Callback, ID, JSONObject, Options } from "@jitsu/protocols/analytics";
|
|
5
5
|
import parse from "./index";
|
|
6
6
|
import { AnalyticsInstance, AnalyticsPlugin } from "analytics";
|
|
7
|
-
import { internalDestinationPlugins } from "./destination-plugins";
|
|
8
7
|
import { loadScript } from "./script-loader";
|
|
8
|
+
import { internalDestinationPlugins } from "./destination-plugins";
|
|
9
|
+
import { jitsuLibraryName, jitsuVersion } from "./version";
|
|
9
10
|
|
|
10
|
-
const config: JitsuOptions = {
|
|
11
|
+
const config: Required<JitsuOptions> = {
|
|
11
12
|
/* Your segment writeKey */
|
|
12
13
|
writeKey: null,
|
|
13
14
|
/* Disable anonymous MTU */
|
|
@@ -15,6 +16,8 @@ const config: JitsuOptions = {
|
|
|
15
16
|
debug: false,
|
|
16
17
|
fetch: null,
|
|
17
18
|
echoEvents: false,
|
|
19
|
+
cookieDomain: undefined,
|
|
20
|
+
runtime: undefined,
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
export const parseQuery = (qs?: string): Record<string, string> => {
|
|
@@ -255,13 +258,13 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
|
|
|
255
258
|
const referrer = runtime.referrer();
|
|
256
259
|
const context = {
|
|
257
260
|
library: {
|
|
258
|
-
name:
|
|
259
|
-
version:
|
|
261
|
+
name: jitsuLibraryName,
|
|
262
|
+
version: jitsuVersion,
|
|
260
263
|
},
|
|
261
264
|
userAgent: runtime.userAgent(),
|
|
262
265
|
locale: runtime.language(),
|
|
263
266
|
screen: runtime.screen(),
|
|
264
|
-
traits: payload.type != "identify" ? { ...(restoreTraits(storage) || {}) } : undefined,
|
|
267
|
+
traits: payload.type != "identify" && payload.type != "group" ? { ...(restoreTraits(storage) || {}) } : undefined,
|
|
265
268
|
page: {
|
|
266
269
|
path: properties.path || (parsedUrl && parsedUrl.pathname),
|
|
267
270
|
referrer: referrer,
|
|
@@ -270,7 +273,7 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
|
|
|
270
273
|
search: properties.search || (parsedUrl && parsedUrl.search),
|
|
271
274
|
title: properties.title || runtime.pageTitle(),
|
|
272
275
|
url: properties.url || url,
|
|
273
|
-
|
|
276
|
+
encoding: properties.encoding || runtime.documentEncoding(),
|
|
274
277
|
},
|
|
275
278
|
campaign: parseUtms(query),
|
|
276
279
|
};
|
|
@@ -279,7 +282,7 @@ function adjustPayload(payload: any, config: JitsuOptions, storage: PersistentSt
|
|
|
279
282
|
timestamp: new Date().toISOString(),
|
|
280
283
|
sentAt: new Date().toISOString(),
|
|
281
284
|
messageId: randomId(properties.path || (parsedUrl && parsedUrl.pathname)),
|
|
282
|
-
writeKey: config.writeKey,
|
|
285
|
+
writeKey: validateWriteKey(config.writeKey),
|
|
283
286
|
context: deepMerge(context, customContext),
|
|
284
287
|
};
|
|
285
288
|
delete withContext.meta;
|
|
@@ -291,6 +294,7 @@ export type DestinationDescriptor = {
|
|
|
291
294
|
id: string;
|
|
292
295
|
destinationType: string;
|
|
293
296
|
credentials: any;
|
|
297
|
+
options: any;
|
|
294
298
|
deviceOptions: DeviceOptions;
|
|
295
299
|
};
|
|
296
300
|
export type AnalyticsPluginDescriptor = {
|
|
@@ -315,12 +319,12 @@ async function processDestinations(
|
|
|
315
319
|
) {
|
|
316
320
|
const promises: Promise<any>[] = [];
|
|
317
321
|
for (const destination of destinations) {
|
|
322
|
+
const credentials = { ...destination.credentials, ...destination.options };
|
|
323
|
+
|
|
318
324
|
if (destination.deviceOptions.type === "internal-plugin") {
|
|
319
325
|
const plugin = internalDestinationPlugins[destination.deviceOptions.name];
|
|
320
326
|
if (plugin) {
|
|
321
327
|
try {
|
|
322
|
-
//to support old versions, where credentials were stored in root
|
|
323
|
-
const credentials = destination.credentials || destination;
|
|
324
328
|
promises.push(plugin.handle(credentials, event));
|
|
325
329
|
} catch (e) {
|
|
326
330
|
console.warn(
|
|
@@ -343,7 +347,7 @@ async function processDestinations(
|
|
|
343
347
|
} else {
|
|
344
348
|
let pluginInstance: any;
|
|
345
349
|
try {
|
|
346
|
-
pluginInstance = (typeof plugin === "function" ? plugin : plugin.init)(
|
|
350
|
+
pluginInstance = (typeof plugin === "function" ? plugin : plugin.init)(credentials);
|
|
347
351
|
} catch (e) {
|
|
348
352
|
console.warn(
|
|
349
353
|
`[JITSU] Error creating plugin '${destination.deviceOptions.moduleVarName}@${destination.deviceOptions.packageCdn}' for destination '${destination.id}': ${e?.message}`,
|
|
@@ -383,6 +387,18 @@ async function processDestinations(
|
|
|
383
387
|
}
|
|
384
388
|
}
|
|
385
389
|
|
|
390
|
+
function validateWriteKey(writeKey?: string): string | undefined {
|
|
391
|
+
if (writeKey) {
|
|
392
|
+
const [, secret] = writeKey.split(":", 2);
|
|
393
|
+
if (!secret) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`Legacy write key detected - ${writeKey}! This format doesn't work anymore, it should be 'key:secret'. Please download a new key from Jitsu UI`
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return writeKey;
|
|
400
|
+
}
|
|
401
|
+
|
|
386
402
|
function send(
|
|
387
403
|
method,
|
|
388
404
|
payload,
|
|
@@ -408,7 +424,7 @@ function send(
|
|
|
408
424
|
// console.log(`[JITSU] Sending event to ${url}: `, JSON.stringify(payload, null, 2));
|
|
409
425
|
// }
|
|
410
426
|
const adjustedPayload = adjustPayload(payload, jitsuConfig, store);
|
|
411
|
-
const authHeader =
|
|
427
|
+
const authHeader = config.writeKey ? { "X-Write-Key": validateWriteKey(config.writeKey) } : {};
|
|
412
428
|
return fetch(url, {
|
|
413
429
|
method: "POST",
|
|
414
430
|
headers: {
|
|
@@ -441,7 +457,7 @@ function send(
|
|
|
441
457
|
}
|
|
442
458
|
if (response.destinations) {
|
|
443
459
|
if (jitsuConfig.debug) {
|
|
444
|
-
console.log(`[JITSU] Processing device
|
|
460
|
+
console.log(`[JITSU] Processing device destinations: `, JSON.stringify(response.destinations, null, 2));
|
|
445
461
|
}
|
|
446
462
|
return processDestinations(response.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
|
|
447
463
|
}
|
|
@@ -471,12 +487,13 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuOptions = {}): AnalyticsPlugin
|
|
|
471
487
|
persistentStorage.removeItem(key);
|
|
472
488
|
},
|
|
473
489
|
});
|
|
490
|
+
const instanceConfig = {
|
|
491
|
+
...config,
|
|
492
|
+
...pluginConfig,
|
|
493
|
+
};
|
|
474
494
|
return {
|
|
475
495
|
name: "jitsu",
|
|
476
|
-
config:
|
|
477
|
-
...config,
|
|
478
|
-
...pluginConfig,
|
|
479
|
-
},
|
|
496
|
+
config: instanceConfig,
|
|
480
497
|
initialize: args => {
|
|
481
498
|
const { config } = args;
|
|
482
499
|
if (config.debug) {
|
|
@@ -504,6 +521,22 @@ const jitsuAnalyticsPlugin = (pluginConfig: JitsuOptions = {}): AnalyticsPlugin
|
|
|
504
521
|
//clear storage cache
|
|
505
522
|
Object.keys(storageCache).forEach(key => delete storageCache[key]);
|
|
506
523
|
},
|
|
524
|
+
methods: {
|
|
525
|
+
//analytics doesn't support group as a base method, so we need to add it manually
|
|
526
|
+
group(groupId?: ID, traits?: JSONObject | null, options?: Options, callback?: Callback) {
|
|
527
|
+
const analyticsInstance = this.instance;
|
|
528
|
+
const user = analyticsInstance.user();
|
|
529
|
+
const userId = options?.userId || user?.userId;
|
|
530
|
+
const anonymousId = options?.anonymousId || user?.anonymousId;
|
|
531
|
+
return send(
|
|
532
|
+
"group",
|
|
533
|
+
{ type: "group", groupId, traits, ...(anonymousId ? { anonymousId } : {}), ...(userId ? { userId } : {}) },
|
|
534
|
+
instanceConfig,
|
|
535
|
+
analyticsInstance,
|
|
536
|
+
cachingStorageWrapper(analyticsInstance.storage)
|
|
537
|
+
);
|
|
538
|
+
},
|
|
539
|
+
},
|
|
507
540
|
};
|
|
508
541
|
};
|
|
509
542
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { loadScript } from "../script-loader";
|
|
2
|
+
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
3
|
+
import { applyFilters, CommonDestinationCredentials, InternalPlugin } from "./index";
|
|
4
|
+
|
|
5
|
+
const defaultScriptSrc = "https://www.googletagmanager.com/gtag/js";
|
|
6
|
+
|
|
7
|
+
export type GtmDestinationCredentials = {
|
|
8
|
+
debug: boolean;
|
|
9
|
+
containerId: string;
|
|
10
|
+
dataLayerName: string;
|
|
11
|
+
preview: string;
|
|
12
|
+
auth: string;
|
|
13
|
+
customScriptSrc: string;
|
|
14
|
+
} & CommonDestinationCredentials;
|
|
15
|
+
|
|
16
|
+
export const gtmPlugin: InternalPlugin<GtmDestinationCredentials> = {
|
|
17
|
+
id: "gtm",
|
|
18
|
+
async handle(config, payload: AnalyticsClientEvent) {
|
|
19
|
+
if (!applyFilters(payload, config)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
await initGtmIfNeeded(config);
|
|
23
|
+
|
|
24
|
+
const dataLayer = window[config.dataLayerName || "dataLayer"];
|
|
25
|
+
|
|
26
|
+
switch (payload.type) {
|
|
27
|
+
case "page":
|
|
28
|
+
const { properties: pageProperties, context } = payload;
|
|
29
|
+
const pageEvent = {
|
|
30
|
+
event: "page_view",
|
|
31
|
+
url: pageProperties.url,
|
|
32
|
+
title: pageProperties.title,
|
|
33
|
+
referer: context?.page?.referrer ?? "",
|
|
34
|
+
};
|
|
35
|
+
if (config.debug) {
|
|
36
|
+
console.log("gtag push", pageEvent);
|
|
37
|
+
}
|
|
38
|
+
dataLayer.push(pageEvent);
|
|
39
|
+
break;
|
|
40
|
+
case "track":
|
|
41
|
+
const { properties: trackProperties } = payload;
|
|
42
|
+
const trackEvent: any = { event: payload.event, ...trackProperties };
|
|
43
|
+
if (payload.userId) {
|
|
44
|
+
trackEvent.userId = payload.userId;
|
|
45
|
+
}
|
|
46
|
+
if (payload.anonymousId) {
|
|
47
|
+
trackEvent.anonymousId = payload.anonymousId;
|
|
48
|
+
}
|
|
49
|
+
if (config.debug) {
|
|
50
|
+
console.log("gtag push", trackEvent);
|
|
51
|
+
}
|
|
52
|
+
dataLayer.push(trackEvent);
|
|
53
|
+
break;
|
|
54
|
+
case "identify":
|
|
55
|
+
const { traits } = payload;
|
|
56
|
+
const identifyEvent: any = { event: "identify", ...traits };
|
|
57
|
+
if (payload.userId) {
|
|
58
|
+
identifyEvent.userId = payload.userId;
|
|
59
|
+
}
|
|
60
|
+
if (payload.anonymousId) {
|
|
61
|
+
identifyEvent.anonymousId = payload.anonymousId;
|
|
62
|
+
}
|
|
63
|
+
if (config.debug) {
|
|
64
|
+
console.log("gtag push", identifyEvent);
|
|
65
|
+
}
|
|
66
|
+
dataLayer.push(identifyEvent);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type GtmState = "fresh" | "loading" | "loaded" | "failed";
|
|
73
|
+
|
|
74
|
+
function getGtmState(): GtmState {
|
|
75
|
+
return window["__jitsuGtmState"] || "fresh";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function setGtmState(s: GtmState) {
|
|
79
|
+
window["__jitsuGtmState"] = s;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function initGtmIfNeeded(config: GtmDestinationCredentials) {
|
|
83
|
+
if (getGtmState() !== "fresh") {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
setGtmState("loading");
|
|
87
|
+
|
|
88
|
+
const dlName = config.dataLayerName || "dataLayer";
|
|
89
|
+
const dlParam = dlName !== "dataLayer" ? "&l=" + dlName : "";
|
|
90
|
+
const previewParams = config.preview
|
|
91
|
+
? `>m_preview=${config.preview}>m_auth=${config.auth}>m_cookies_win=x`
|
|
92
|
+
: "";
|
|
93
|
+
const scriptSrc = `${config.customScriptSrc || defaultScriptSrc}?id=${config.containerId}${dlParam}${previewParams}`;
|
|
94
|
+
|
|
95
|
+
window[dlName] = window[dlName] || [];
|
|
96
|
+
const gtag = function () {
|
|
97
|
+
window[dlName].push(arguments);
|
|
98
|
+
};
|
|
99
|
+
// @ts-ignore
|
|
100
|
+
gtag("js", new Date());
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
gtag("config", config.containerId);
|
|
103
|
+
|
|
104
|
+
loadScript(scriptSrc)
|
|
105
|
+
.then(() => {
|
|
106
|
+
setGtmState("loaded");
|
|
107
|
+
})
|
|
108
|
+
.catch(e => {
|
|
109
|
+
console.warn(`GTM (containerId=${config.containerId}) init failed: ${e.message}`, e);
|
|
110
|
+
setGtmState("failed");
|
|
111
|
+
});
|
|
112
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
2
|
+
import { tagPlugin } from "./tag";
|
|
3
|
+
import { logrocketPlugin } from "./logrocket";
|
|
4
|
+
import { gtmPlugin } from "./gtm";
|
|
5
|
+
|
|
6
|
+
export type InternalPlugin<T> = {
|
|
7
|
+
id: string;
|
|
8
|
+
handle(config: T, payload: AnalyticsClientEvent): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type CommonDestinationCredentials = {
|
|
12
|
+
hosts?: string;
|
|
13
|
+
events?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function satisfyFilter(filter: string, subject: string | undefined): boolean {
|
|
17
|
+
return filter === "*" || filter.toLowerCase().trim() === (subject || "").trim().toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function satisfyDomainFilter(filter: string, subject: string | undefined): boolean {
|
|
21
|
+
if (filter === "*") {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
subject = subject || "";
|
|
25
|
+
|
|
26
|
+
if (filter.startsWith("*.")) {
|
|
27
|
+
return subject.endsWith(filter.substring(1));
|
|
28
|
+
} else {
|
|
29
|
+
return filter === subject;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function applyFilters(event: AnalyticsClientEvent, creds: CommonDestinationCredentials): boolean {
|
|
34
|
+
const { hosts = "*", events = "*" } = creds;
|
|
35
|
+
const eventsArray = events.split("\n");
|
|
36
|
+
return (
|
|
37
|
+
!!hosts.split("\n").find(hostFilter => satisfyDomainFilter(hostFilter, event.context?.host)) &&
|
|
38
|
+
(!!eventsArray.find(eventFilter => satisfyFilter(eventFilter, event.type)) ||
|
|
39
|
+
!!eventsArray.find(eventFilter => satisfyFilter(eventFilter, event.event)))
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const internalDestinationPlugins: Record<string, InternalPlugin<any>> = {
|
|
44
|
+
[tagPlugin.id]: tagPlugin,
|
|
45
|
+
[gtmPlugin.id]: gtmPlugin,
|
|
46
|
+
[logrocketPlugin.id]: logrocketPlugin,
|
|
47
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { loadScript } from "../script-loader";
|
|
2
|
+
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
3
|
+
import { applyFilters, CommonDestinationCredentials, InternalPlugin } from "./index";
|
|
4
|
+
|
|
5
|
+
export type LogRocketDestinationCredentials = {
|
|
6
|
+
appId: string;
|
|
7
|
+
} & CommonDestinationCredentials;
|
|
8
|
+
|
|
9
|
+
export const logrocketPlugin: InternalPlugin<LogRocketDestinationCredentials> = {
|
|
10
|
+
id: "logrocket",
|
|
11
|
+
async handle(config, payload: AnalyticsClientEvent) {
|
|
12
|
+
if (!applyFilters(payload, config)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
initLogrocketIfNeeded(config.appId);
|
|
16
|
+
|
|
17
|
+
const action = logRocket => {
|
|
18
|
+
if (payload.type === "identify" && payload.userId) {
|
|
19
|
+
logRocket.identify(payload.userId, payload.traits || {});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
getLogRocketQueue().push(action);
|
|
23
|
+
if (getLogRocketState() === "loaded") {
|
|
24
|
+
flushLogRocketQueue(window["LogRocket"]);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type LogRocketState = "fresh" | "loading" | "loaded" | "failed";
|
|
30
|
+
|
|
31
|
+
function getLogRocketState(): LogRocketState {
|
|
32
|
+
return window["__jitsuLrState"] || "fresh";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function setLogRocketState(s: LogRocketState) {
|
|
36
|
+
window["__jitsuLrState"] = s;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getLogRocketQueue(): ((lr: LogRocket) => void | Promise<void>)[] {
|
|
40
|
+
return window["__jitsuLrQueue"] || (window["__jitsuLrQueue"] = []);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type LogRocket = any;
|
|
44
|
+
|
|
45
|
+
function flushLogRocketQueue(lr: LogRocket) {
|
|
46
|
+
const queue = getLogRocketQueue();
|
|
47
|
+
|
|
48
|
+
while (queue.length > 0) {
|
|
49
|
+
const method = queue.shift();
|
|
50
|
+
try {
|
|
51
|
+
const res = method(lr);
|
|
52
|
+
if (res) {
|
|
53
|
+
res.catch(e => console.warn(`Async LogRocket method failed: ${e.message}`, e));
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.warn(`LogRocket method failed: ${e.message}`, e);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function initLogrocketIfNeeded(appId: string) {
|
|
62
|
+
if (getLogRocketState() !== "fresh") {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
setLogRocketState("loading");
|
|
66
|
+
loadScript(`https://cdn.lr-ingest.io/LogRocket.min.js`, { crossOrigin: "anonymous" })
|
|
67
|
+
.then(() => {
|
|
68
|
+
if (window["LogRocket"]) {
|
|
69
|
+
try {
|
|
70
|
+
window["LogRocket"].init(appId);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
console.warn(`LogRocket (id=${appId}) init failed: ${e.message}`, e);
|
|
73
|
+
setLogRocketState("failed");
|
|
74
|
+
}
|
|
75
|
+
setLogRocketState("loaded");
|
|
76
|
+
flushLogRocketQueue(window["LogRocket"]);
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
.catch(e => {
|
|
80
|
+
console.warn(`LogRocket (id=${appId}) init failed: ${e.message}`, e);
|
|
81
|
+
setLogRocketState("failed");
|
|
82
|
+
});
|
|
83
|
+
}
|
|
@@ -1,33 +1,12 @@
|
|
|
1
1
|
import { AnalyticsClientEvent } from "@jitsu/protocols/analytics";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export type InternalPlugin<T> = {
|
|
5
|
-
id: string;
|
|
6
|
-
handle(config: T, payload: AnalyticsClientEvent): Promise<void>;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export type CommonDestinationCredentials = {
|
|
10
|
-
hosts?: string[];
|
|
11
|
-
events?: string[];
|
|
12
|
-
};
|
|
2
|
+
import { applyFilters, CommonDestinationCredentials, InternalPlugin } from "./index";
|
|
3
|
+
import { isInBrowser, randomId } from "../analytics-plugin";
|
|
13
4
|
|
|
14
5
|
export type TagDestinationCredentials = {
|
|
15
6
|
code: string;
|
|
16
7
|
} & CommonDestinationCredentials;
|
|
17
8
|
|
|
18
|
-
|
|
19
|
-
return filter === "*" || filter.toLowerCase().trim() === (subject || "").trim().toLowerCase();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function applyFilters(event: AnalyticsClientEvent, creds: CommonDestinationCredentials): boolean {
|
|
23
|
-
const { hosts = ["*"], events = ["*"] } = creds;
|
|
24
|
-
return (
|
|
25
|
-
!!hosts.find(hostFilter => satisfyFilter(hostFilter, event.context?.host)) &&
|
|
26
|
-
!!events.find(eventFilter => satisfyFilter(eventFilter, event.type))
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const tagPlugin: InternalPlugin<TagDestinationCredentials> = {
|
|
9
|
+
export const tagPlugin: InternalPlugin<TagDestinationCredentials> = {
|
|
31
10
|
id: "tag",
|
|
32
11
|
async handle(config, payload: AnalyticsClientEvent) {
|
|
33
12
|
if (!applyFilters(payload, config)) {
|
|
@@ -97,7 +76,3 @@ function execJs(code: string, event: any) {
|
|
|
97
76
|
function replaceMacro(code, event) {
|
|
98
77
|
return code.replace(/{{\s*event\s*}}/g, JSON.stringify(event));
|
|
99
78
|
}
|
|
100
|
-
|
|
101
|
-
export const internalDestinationPlugins: Record<string, InternalPlugin<any>> = {
|
|
102
|
-
[tagPlugin.id]: tagPlugin,
|
|
103
|
-
};
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Analytics from "analytics";
|
|
2
2
|
import { AnalyticsInterface, JitsuOptions, RuntimeFacade } from "./jitsu";
|
|
3
3
|
import jitsuAnalyticsPlugin, { emptyRuntime, isInBrowser, windowRuntime } from "./analytics-plugin";
|
|
4
|
-
import {
|
|
5
|
-
import e from "express";
|
|
4
|
+
import { Callback, DispatchedEvent, ID, JSONObject, Options } from "@jitsu/protocols/analytics";
|
|
6
5
|
|
|
7
6
|
export default function parse(input) {
|
|
8
7
|
let value = input;
|
|
@@ -29,6 +28,7 @@ export const emptyAnalytics = {
|
|
|
29
28
|
page: () => Promise.resolve(),
|
|
30
29
|
user: () => ({}),
|
|
31
30
|
identify: () => Promise.resolve({}),
|
|
31
|
+
group: () => Promise.resolve({}),
|
|
32
32
|
reset: () => Promise.resolve({}),
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -54,7 +54,17 @@ function createUnderlyingAnalyticsInstance(
|
|
|
54
54
|
return originalPage(...args);
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
-
return
|
|
57
|
+
return {
|
|
58
|
+
...analytics,
|
|
59
|
+
group(groupId?: ID, traits?: JSONObject | null, options?: Options, callback?: Callback): Promise<DispatchedEvent> {
|
|
60
|
+
for (const plugin of Object.values(analytics.plugins)) {
|
|
61
|
+
if (plugin["group"]) {
|
|
62
|
+
plugin["group"](groupId, traits, options, callback);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Promise.resolve({});
|
|
66
|
+
},
|
|
67
|
+
} as AnalyticsInterface;
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
export function jitsuAnalytics(opts: JitsuOptions): AnalyticsInterface {
|
package/src/version.ts
ADDED