@fabricorg/experiments-web-adapters 0.0.2
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/index.cjs +116 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +57 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/package.json +36 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
function snowplowAdapter(options = {}) {
|
|
5
|
+
var _a;
|
|
6
|
+
const schema = (_a = options.schema) != null ? _a : "iglu:io.fabric.experiments/exposure/jsonschema/1-0-0";
|
|
7
|
+
return (record) => {
|
|
8
|
+
var _a2;
|
|
9
|
+
const tracker = (_a2 = options.tracker) != null ? _a2 : globalThis.snowplow;
|
|
10
|
+
if (!tracker) return;
|
|
11
|
+
tracker("trackSelfDescribingEvent", {
|
|
12
|
+
event: {
|
|
13
|
+
schema,
|
|
14
|
+
data: {
|
|
15
|
+
experimentId: record.experimentId,
|
|
16
|
+
variantKey: record.variantKey,
|
|
17
|
+
subjectId: record.subjectId,
|
|
18
|
+
manifestVersion: record.manifestVersion,
|
|
19
|
+
at: record.at,
|
|
20
|
+
failure: record.failure
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function gaAdapter(options = {}) {
|
|
27
|
+
var _a;
|
|
28
|
+
const eventName = (_a = options.eventName) != null ? _a : "experiment_exposure";
|
|
29
|
+
return (record) => {
|
|
30
|
+
var _a2;
|
|
31
|
+
const gtag = (_a2 = options.gtag) != null ? _a2 : globalThis.gtag;
|
|
32
|
+
if (!gtag) return;
|
|
33
|
+
gtag("event", eventName, {
|
|
34
|
+
experiment_id: record.experimentId,
|
|
35
|
+
variant_key: record.variantKey,
|
|
36
|
+
manifest_version: record.manifestVersion
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function dataLayerAdapter(options = {}) {
|
|
41
|
+
var _a;
|
|
42
|
+
const eventName = (_a = options.eventName) != null ? _a : "fx_exposure";
|
|
43
|
+
return (record) => {
|
|
44
|
+
var _a2;
|
|
45
|
+
const w = globalThis;
|
|
46
|
+
const dl = (_a2 = options.dataLayer) != null ? _a2 : w.dataLayer = w.dataLayer || [];
|
|
47
|
+
dl.push({
|
|
48
|
+
event: eventName,
|
|
49
|
+
fx_experiment_id: record.experimentId,
|
|
50
|
+
fx_variant_key: record.variantKey,
|
|
51
|
+
fx_subject_id: record.subjectId,
|
|
52
|
+
fx_manifest_version: record.manifestVersion
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function compose(...adapters) {
|
|
57
|
+
return (record) => {
|
|
58
|
+
for (const a of adapters) {
|
|
59
|
+
try {
|
|
60
|
+
a(record);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function snowplowFailureAdapter(options = {}) {
|
|
67
|
+
var _a;
|
|
68
|
+
const schema = (_a = options.schema) != null ? _a : "iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0";
|
|
69
|
+
return (record) => {
|
|
70
|
+
var _a2;
|
|
71
|
+
if (!record.failure) return;
|
|
72
|
+
const tracker = (_a2 = options.tracker) != null ? _a2 : globalThis.snowplow;
|
|
73
|
+
if (!tracker) return;
|
|
74
|
+
tracker("trackSelfDescribingEvent", {
|
|
75
|
+
event: {
|
|
76
|
+
schema,
|
|
77
|
+
data: {
|
|
78
|
+
experimentId: record.experimentId,
|
|
79
|
+
variantKey: record.variantKey,
|
|
80
|
+
subjectId: record.subjectId,
|
|
81
|
+
manifestVersion: record.manifestVersion,
|
|
82
|
+
at: record.at,
|
|
83
|
+
message: record.failure.message,
|
|
84
|
+
stack: record.failure.stack
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function dataLayerFailureAdapter(options = {}) {
|
|
91
|
+
var _a;
|
|
92
|
+
const eventName = (_a = options.eventName) != null ? _a : "fx_recipe_failure";
|
|
93
|
+
return (record) => {
|
|
94
|
+
var _a2;
|
|
95
|
+
if (!record.failure) return;
|
|
96
|
+
const w = globalThis;
|
|
97
|
+
const dl = (_a2 = options.dataLayer) != null ? _a2 : w.dataLayer = w.dataLayer || [];
|
|
98
|
+
dl.push({
|
|
99
|
+
event: eventName,
|
|
100
|
+
fx_experiment_id: record.experimentId,
|
|
101
|
+
fx_variant_key: record.variantKey,
|
|
102
|
+
fx_subject_id: record.subjectId,
|
|
103
|
+
fx_manifest_version: record.manifestVersion,
|
|
104
|
+
fx_failure_message: record.failure.message
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
exports.compose = compose;
|
|
110
|
+
exports.dataLayerAdapter = dataLayerAdapter;
|
|
111
|
+
exports.dataLayerFailureAdapter = dataLayerFailureAdapter;
|
|
112
|
+
exports.gaAdapter = gaAdapter;
|
|
113
|
+
exports.snowplowAdapter = snowplowAdapter;
|
|
114
|
+
exports.snowplowFailureAdapter = snowplowFailureAdapter;
|
|
115
|
+
//# sourceMappingURL=index.cjs.map
|
|
116
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ??\n (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag =\n options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n const dl = options.dataLayer ?? (w.dataLayer = w.dataLayer || []);\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema =\n options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ??\n (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(\n options: DataLayerAdapterOptions = {},\n): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n const dl = options.dataLayer ?? (w.dataLayer = w.dataLayer || []);\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ExposureRecord } from '@fabricorg/experiments-web';
|
|
2
|
+
|
|
3
|
+
type ExposureAdapter = (record: ExposureRecord) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Snowplow self-describing exposure event.
|
|
6
|
+
*
|
|
7
|
+
* Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0
|
|
8
|
+
* (host the schema in your Iglu repo to validate downstream).
|
|
9
|
+
*/
|
|
10
|
+
interface SnowplowAdapterOptions {
|
|
11
|
+
/** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */
|
|
12
|
+
tracker?: (...args: unknown[]) => void;
|
|
13
|
+
/** Schema URI. Override if you publish a custom schema. */
|
|
14
|
+
schema?: string;
|
|
15
|
+
}
|
|
16
|
+
declare function snowplowAdapter(options?: SnowplowAdapterOptions): ExposureAdapter;
|
|
17
|
+
/**
|
|
18
|
+
* Google Analytics 4 (gtag) adapter.
|
|
19
|
+
* Sends an `experiment_exposure` event with custom dimensions.
|
|
20
|
+
*/
|
|
21
|
+
interface GaAdapterOptions {
|
|
22
|
+
gtag?: (...args: unknown[]) => void;
|
|
23
|
+
/** Override the event name. Default: `experiment_exposure`. */
|
|
24
|
+
eventName?: string;
|
|
25
|
+
}
|
|
26
|
+
declare function gaAdapter(options?: GaAdapterOptions): ExposureAdapter;
|
|
27
|
+
/**
|
|
28
|
+
* Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.
|
|
29
|
+
* This is also the default tag-loader behavior.
|
|
30
|
+
*/
|
|
31
|
+
interface DataLayerAdapterOptions {
|
|
32
|
+
/** Override the dataLayer reference (tests). */
|
|
33
|
+
dataLayer?: Array<Record<string, unknown>>;
|
|
34
|
+
/** Override the event name. Default: `fx_exposure`. */
|
|
35
|
+
eventName?: string;
|
|
36
|
+
}
|
|
37
|
+
declare function dataLayerAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
|
|
38
|
+
/**
|
|
39
|
+
* Fan out a single exposure to multiple adapters. Each adapter is wrapped in
|
|
40
|
+
* a try/catch so a third-party tracker error never breaks the chain.
|
|
41
|
+
*/
|
|
42
|
+
declare function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter;
|
|
43
|
+
/**
|
|
44
|
+
* Snowplow self-describing event for variant failures.
|
|
45
|
+
*
|
|
46
|
+
* Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0
|
|
47
|
+
* Fires once per (experimentId, variantKey, message) — useful for alarming
|
|
48
|
+
* on variant-code crashes without cluttering the exposure stream.
|
|
49
|
+
*/
|
|
50
|
+
interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {
|
|
51
|
+
schema?: string;
|
|
52
|
+
}
|
|
53
|
+
declare function snowplowFailureAdapter(options?: SnowplowFailureAdapterOptions): ExposureAdapter;
|
|
54
|
+
/** dataLayer push for variant failures — pairs with the default exposure adapter. */
|
|
55
|
+
declare function dataLayerFailureAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
|
|
56
|
+
|
|
57
|
+
export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ExposureRecord } from '@fabricorg/experiments-web';
|
|
2
|
+
|
|
3
|
+
type ExposureAdapter = (record: ExposureRecord) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Snowplow self-describing exposure event.
|
|
6
|
+
*
|
|
7
|
+
* Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0
|
|
8
|
+
* (host the schema in your Iglu repo to validate downstream).
|
|
9
|
+
*/
|
|
10
|
+
interface SnowplowAdapterOptions {
|
|
11
|
+
/** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */
|
|
12
|
+
tracker?: (...args: unknown[]) => void;
|
|
13
|
+
/** Schema URI. Override if you publish a custom schema. */
|
|
14
|
+
schema?: string;
|
|
15
|
+
}
|
|
16
|
+
declare function snowplowAdapter(options?: SnowplowAdapterOptions): ExposureAdapter;
|
|
17
|
+
/**
|
|
18
|
+
* Google Analytics 4 (gtag) adapter.
|
|
19
|
+
* Sends an `experiment_exposure` event with custom dimensions.
|
|
20
|
+
*/
|
|
21
|
+
interface GaAdapterOptions {
|
|
22
|
+
gtag?: (...args: unknown[]) => void;
|
|
23
|
+
/** Override the event name. Default: `experiment_exposure`. */
|
|
24
|
+
eventName?: string;
|
|
25
|
+
}
|
|
26
|
+
declare function gaAdapter(options?: GaAdapterOptions): ExposureAdapter;
|
|
27
|
+
/**
|
|
28
|
+
* Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.
|
|
29
|
+
* This is also the default tag-loader behavior.
|
|
30
|
+
*/
|
|
31
|
+
interface DataLayerAdapterOptions {
|
|
32
|
+
/** Override the dataLayer reference (tests). */
|
|
33
|
+
dataLayer?: Array<Record<string, unknown>>;
|
|
34
|
+
/** Override the event name. Default: `fx_exposure`. */
|
|
35
|
+
eventName?: string;
|
|
36
|
+
}
|
|
37
|
+
declare function dataLayerAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
|
|
38
|
+
/**
|
|
39
|
+
* Fan out a single exposure to multiple adapters. Each adapter is wrapped in
|
|
40
|
+
* a try/catch so a third-party tracker error never breaks the chain.
|
|
41
|
+
*/
|
|
42
|
+
declare function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter;
|
|
43
|
+
/**
|
|
44
|
+
* Snowplow self-describing event for variant failures.
|
|
45
|
+
*
|
|
46
|
+
* Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0
|
|
47
|
+
* Fires once per (experimentId, variantKey, message) — useful for alarming
|
|
48
|
+
* on variant-code crashes without cluttering the exposure stream.
|
|
49
|
+
*/
|
|
50
|
+
interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {
|
|
51
|
+
schema?: string;
|
|
52
|
+
}
|
|
53
|
+
declare function snowplowFailureAdapter(options?: SnowplowFailureAdapterOptions): ExposureAdapter;
|
|
54
|
+
/** dataLayer push for variant failures — pairs with the default exposure adapter. */
|
|
55
|
+
declare function dataLayerFailureAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
|
|
56
|
+
|
|
57
|
+
export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
function snowplowAdapter(options = {}) {
|
|
3
|
+
var _a;
|
|
4
|
+
const schema = (_a = options.schema) != null ? _a : "iglu:io.fabric.experiments/exposure/jsonschema/1-0-0";
|
|
5
|
+
return (record) => {
|
|
6
|
+
var _a2;
|
|
7
|
+
const tracker = (_a2 = options.tracker) != null ? _a2 : globalThis.snowplow;
|
|
8
|
+
if (!tracker) return;
|
|
9
|
+
tracker("trackSelfDescribingEvent", {
|
|
10
|
+
event: {
|
|
11
|
+
schema,
|
|
12
|
+
data: {
|
|
13
|
+
experimentId: record.experimentId,
|
|
14
|
+
variantKey: record.variantKey,
|
|
15
|
+
subjectId: record.subjectId,
|
|
16
|
+
manifestVersion: record.manifestVersion,
|
|
17
|
+
at: record.at,
|
|
18
|
+
failure: record.failure
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function gaAdapter(options = {}) {
|
|
25
|
+
var _a;
|
|
26
|
+
const eventName = (_a = options.eventName) != null ? _a : "experiment_exposure";
|
|
27
|
+
return (record) => {
|
|
28
|
+
var _a2;
|
|
29
|
+
const gtag = (_a2 = options.gtag) != null ? _a2 : globalThis.gtag;
|
|
30
|
+
if (!gtag) return;
|
|
31
|
+
gtag("event", eventName, {
|
|
32
|
+
experiment_id: record.experimentId,
|
|
33
|
+
variant_key: record.variantKey,
|
|
34
|
+
manifest_version: record.manifestVersion
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function dataLayerAdapter(options = {}) {
|
|
39
|
+
var _a;
|
|
40
|
+
const eventName = (_a = options.eventName) != null ? _a : "fx_exposure";
|
|
41
|
+
return (record) => {
|
|
42
|
+
var _a2;
|
|
43
|
+
const w = globalThis;
|
|
44
|
+
const dl = (_a2 = options.dataLayer) != null ? _a2 : w.dataLayer = w.dataLayer || [];
|
|
45
|
+
dl.push({
|
|
46
|
+
event: eventName,
|
|
47
|
+
fx_experiment_id: record.experimentId,
|
|
48
|
+
fx_variant_key: record.variantKey,
|
|
49
|
+
fx_subject_id: record.subjectId,
|
|
50
|
+
fx_manifest_version: record.manifestVersion
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function compose(...adapters) {
|
|
55
|
+
return (record) => {
|
|
56
|
+
for (const a of adapters) {
|
|
57
|
+
try {
|
|
58
|
+
a(record);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function snowplowFailureAdapter(options = {}) {
|
|
65
|
+
var _a;
|
|
66
|
+
const schema = (_a = options.schema) != null ? _a : "iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0";
|
|
67
|
+
return (record) => {
|
|
68
|
+
var _a2;
|
|
69
|
+
if (!record.failure) return;
|
|
70
|
+
const tracker = (_a2 = options.tracker) != null ? _a2 : globalThis.snowplow;
|
|
71
|
+
if (!tracker) return;
|
|
72
|
+
tracker("trackSelfDescribingEvent", {
|
|
73
|
+
event: {
|
|
74
|
+
schema,
|
|
75
|
+
data: {
|
|
76
|
+
experimentId: record.experimentId,
|
|
77
|
+
variantKey: record.variantKey,
|
|
78
|
+
subjectId: record.subjectId,
|
|
79
|
+
manifestVersion: record.manifestVersion,
|
|
80
|
+
at: record.at,
|
|
81
|
+
message: record.failure.message,
|
|
82
|
+
stack: record.failure.stack
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function dataLayerFailureAdapter(options = {}) {
|
|
89
|
+
var _a;
|
|
90
|
+
const eventName = (_a = options.eventName) != null ? _a : "fx_recipe_failure";
|
|
91
|
+
return (record) => {
|
|
92
|
+
var _a2;
|
|
93
|
+
if (!record.failure) return;
|
|
94
|
+
const w = globalThis;
|
|
95
|
+
const dl = (_a2 = options.dataLayer) != null ? _a2 : w.dataLayer = w.dataLayer || [];
|
|
96
|
+
dl.push({
|
|
97
|
+
event: eventName,
|
|
98
|
+
fx_experiment_id: record.experimentId,
|
|
99
|
+
fx_variant_key: record.variantKey,
|
|
100
|
+
fx_subject_id: record.subjectId,
|
|
101
|
+
fx_manifest_version: record.manifestVersion,
|
|
102
|
+
fx_failure_message: record.failure.message
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export { compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
109
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":"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","file":"index.js","sourcesContent":["import type { ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ??\n (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag =\n options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n const dl = options.dataLayer ?? (w.dataLayer = w.dataLayer || []);\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema =\n options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ??\n (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(\n options: DataLayerAdapterOptions = {},\n): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n const dl = options.dataLayer ?? (w.dataLayer = w.dataLayer || []);\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fabricorg/experiments-web-adapters",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"registry": "https://registry.npmjs.org",
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"description": "Pluggable exposure adapters for @fabricorg/experiments-web — Snowplow, GA, GTM, dataLayer.",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
|
|
18
|
+
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": ["dist"],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"type-check": "tsc --noEmit",
|
|
25
|
+
"test": "vitest run --passWithNoTests",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@fabricorg/experiments-web": "workspace:*"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"tsup": "^8.3.5",
|
|
33
|
+
"typescript": "^5.8.3",
|
|
34
|
+
"vitest": "^2.1.8"
|
|
35
|
+
}
|
|
36
|
+
}
|