@se-studio/ab-testing 7.0.2 → 8.0.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/CHANGELOG.md +20 -0
- package/dist/codegen/cli.js +1 -0
- package/dist/codegen/cli.js.map +1 -1
- package/dist/components/AbTestReporter.d.ts.map +1 -1
- package/dist/components/AbTestReporter.js +2 -9
- package/dist/components/AbTestReporter.js.map +1 -1
- package/dist/components/AbTestUtmScript.d.ts +5 -2
- package/dist/components/AbTestUtmScript.d.ts.map +1 -1
- package/dist/components/AbTestUtmScript.js +15 -8
- package/dist/components/AbTestUtmScript.js.map +1 -1
- package/dist/hooks/useAbTestAssignments.d.ts +3 -2
- package/dist/hooks/useAbTestAssignments.d.ts.map +1 -1
- package/dist/hooks/useAbTestAssignments.js +3 -2
- package/dist/hooks/useAbTestAssignments.js.map +1 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/middleware/assignment.d.ts +0 -5
- package/dist/middleware/assignment.d.ts.map +1 -1
- package/dist/middleware/assignment.js +49 -22
- package/dist/middleware/assignment.js.map +1 -1
- package/dist/middleware/cache.d.ts.map +1 -1
- package/dist/middleware/cache.js +18 -6
- package/dist/middleware/cache.js.map +1 -1
- package/dist/middleware/handler.d.ts +9 -56
- package/dist/middleware/handler.d.ts.map +1 -1
- package/dist/middleware/handler.js +121 -214
- package/dist/middleware/handler.js.map +1 -1
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/prune.d.ts +13 -0
- package/dist/middleware/prune.d.ts.map +1 -0
- package/dist/middleware/prune.js +29 -0
- package/dist/middleware/prune.js.map +1 -0
- package/dist/middleware/types.d.ts +18 -11
- package/dist/middleware/types.d.ts.map +1 -1
- package/dist/middleware/urlParams.d.ts +7 -0
- package/dist/middleware/urlParams.d.ts.map +1 -0
- package/dist/middleware/urlParams.js +20 -0
- package/dist/middleware/urlParams.js.map +1 -0
- package/dist/middleware/variantId.d.ts +9 -0
- package/dist/middleware/variantId.d.ts.map +1 -0
- package/dist/middleware/variantId.js +12 -0
- package/dist/middleware/variantId.js.map +1 -0
- package/dist/reporting/buildExperimentImpression.d.ts +6 -0
- package/dist/reporting/buildExperimentImpression.d.ts.map +1 -0
- package/dist/reporting/buildExperimentImpression.js +22 -0
- package/dist/reporting/buildExperimentImpression.js.map +1 -0
- package/dist/types.d.ts +23 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook/handler.d.ts +19 -26
- package/dist/webhook/handler.d.ts.map +1 -1
- package/dist/webhook/handler.js +27 -22
- package/dist/webhook/handler.js.map +1 -1
- package/dist/webhook/index.d.ts +1 -1
- package/dist/webhook/index.d.ts.map +1 -1
- package/dist/webhook/index.js +1 -1
- package/dist/webhook/index.js.map +1 -1
- package/package.json +7 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply url_params to a URL, optionally respecting existing query keys.
|
|
3
|
+
*
|
|
4
|
+
* @returns true if any param was set
|
|
5
|
+
*/
|
|
6
|
+
export function applyUrlParams(url, urlParams, respectExisting) {
|
|
7
|
+
if (!urlParams) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
let changed = false;
|
|
11
|
+
for (const [key, value] of Object.entries(urlParams)) {
|
|
12
|
+
if (respectExisting && url.searchParams.has(key)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
url.searchParams.set(key, value);
|
|
16
|
+
changed = true;
|
|
17
|
+
}
|
|
18
|
+
return changed;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=urlParams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlParams.js","sourceRoot":"","sources":["../../src/middleware/urlParams.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAQ,EACR,SAA6C,EAC7C,eAAwB;IAExB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,eAAe,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,SAAS;QACX,CAAC;QACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the variant_id string for a bucket assignment.
|
|
3
|
+
*
|
|
4
|
+
* @param isControl - Whether this is the control bucket
|
|
5
|
+
* @param variantLabel - CMS variant_label for the bucket
|
|
6
|
+
* @param fallbackSlug - Fallback label when variant_label is absent
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildVariantId(isControl: boolean, variantLabel: string | undefined, fallbackSlug: string): string;
|
|
9
|
+
//# sourceMappingURL=variantId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variantId.d.ts","sourceRoot":"","sources":["../../src/middleware/variantId.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,YAAY,EAAE,MAAM,GACnB,MAAM,CAGR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the variant_id string for a bucket assignment.
|
|
3
|
+
*
|
|
4
|
+
* @param isControl - Whether this is the control bucket
|
|
5
|
+
* @param variantLabel - CMS variant_label for the bucket
|
|
6
|
+
* @param fallbackSlug - Fallback label when variant_label is absent
|
|
7
|
+
*/
|
|
8
|
+
export function buildVariantId(isControl, variantLabel, fallbackSlug) {
|
|
9
|
+
const label = variantLabel ?? fallbackSlug;
|
|
10
|
+
return `${isControl ? 'control' : 'variant'}:${label}`;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=variantId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variantId.js","sourceRoot":"","sources":["../../src/middleware/variantId.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAkB,EAClB,YAAgC,EAChC,YAAoB;IAEpB,MAAM,KAAK,GAAG,YAAY,IAAI,YAAY,CAAC;IAC3C,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AbTestAssignment } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Snake_case experiment_impression payload for analytics adapters.
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildExperimentImpression(testId: string, assignment: AbTestAssignment): Record<string, string>;
|
|
6
|
+
//# sourceMappingURL=buildExperimentImpression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildExperimentImpression.d.ts","sourceRoot":"","sources":["../../src/reporting/buildExperimentImpression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,gBAAgB,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBxB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snake_case experiment_impression payload for analytics adapters.
|
|
3
|
+
*/
|
|
4
|
+
export function buildExperimentImpression(testId, assignment) {
|
|
5
|
+
const payload = {
|
|
6
|
+
experiment_id: testId,
|
|
7
|
+
experiment_name: assignment.experiment_name,
|
|
8
|
+
variant_id: assignment.variant_id,
|
|
9
|
+
variant_slug: assignment.variant_slug,
|
|
10
|
+
original_path: assignment.original_path,
|
|
11
|
+
};
|
|
12
|
+
if (assignment.reporting_event) {
|
|
13
|
+
payload.reporting_event = assignment.reporting_event;
|
|
14
|
+
}
|
|
15
|
+
if (assignment.reporting_params) {
|
|
16
|
+
for (const [key, value] of Object.entries(assignment.reporting_params)) {
|
|
17
|
+
payload[key] = value;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return payload;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=buildExperimentImpression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildExperimentImpression.js","sourceRoot":"","sources":["../../src/reporting/buildExperimentImpression.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAc,EACd,UAA4B;IAE5B,MAAM,OAAO,GAA2B;QACtC,aAAa,EAAE,MAAM;QACrB,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,YAAY,EAAE,UAAU,CAAC,YAAY;QACrC,aAAa,EAAE,UAAU,CAAC,aAAa;KACxC,CAAC;IAEF,IAAI,UAAU,CAAC,eAAe,EAAE,CAAC;QAC/B,OAAO,CAAC,eAAe,GAAG,UAAU,CAAC,eAAe,CAAC;IACvD,CAAC;IAED,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -19,8 +19,14 @@ export interface AbTestVariant {
|
|
|
19
19
|
export interface AbTestVariantConfig {
|
|
20
20
|
/** Traffic weight for this variant (0-1, all weights should sum to 1) */
|
|
21
21
|
weight: number;
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/** CMS label for this bucket; drives variant_id suffix */
|
|
23
|
+
variant_label?: string;
|
|
24
|
+
/** Optional per-bucket analytics event name */
|
|
25
|
+
reporting_event?: string;
|
|
26
|
+
/** Query params to inject when injectUrlParams is enabled on the test */
|
|
27
|
+
url_params?: Record<string, string>;
|
|
28
|
+
/** Arbitrary key-value pairs merged into experiment_impression payloads */
|
|
29
|
+
reporting_params?: Record<string, string>;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* A/B test configuration stored in the blob store.
|
|
@@ -35,10 +41,12 @@ export interface AbTest {
|
|
|
35
41
|
controlSlug: string;
|
|
36
42
|
/** Optional URL query parameters to match (e.g., "utm_source=google") */
|
|
37
43
|
searchParameters?: string;
|
|
38
|
-
/**
|
|
44
|
+
/** Analytics experiment name (defaults to cmsLabel) */
|
|
39
45
|
trackingLabel?: string;
|
|
40
46
|
/** Whether the test is currently active */
|
|
41
47
|
enabled: boolean;
|
|
48
|
+
/** When true, inject url_params from the assigned bucket into the request URL */
|
|
49
|
+
injectUrlParams?: boolean;
|
|
42
50
|
/** Array of variant configurations with weights. Index 0 = control, 1+ = variants */
|
|
43
51
|
configuration: AbTestVariantConfig[];
|
|
44
52
|
/** Array of variants to test against the control */
|
|
@@ -49,14 +57,20 @@ export interface AbTest {
|
|
|
49
57
|
* Each test has its own assignment keyed by test ID.
|
|
50
58
|
*/
|
|
51
59
|
export interface AbTestAssignment {
|
|
52
|
-
/** Analytics
|
|
53
|
-
|
|
60
|
+
/** Analytics experiment name for this test */
|
|
61
|
+
experiment_name: string;
|
|
62
|
+
/** Bucket identifier, e.g. "control:normal-cta" or "variant:home-kids" */
|
|
63
|
+
variant_id: string;
|
|
54
64
|
/** Slug of the assigned variant, or "control" */
|
|
55
|
-
|
|
56
|
-
/** Optional HubSpot event name for this variant */
|
|
57
|
-
hubspot_event?: string;
|
|
65
|
+
variant_slug: string;
|
|
58
66
|
/** Original URL path where the test was assigned */
|
|
59
|
-
original_path
|
|
67
|
+
original_path: string;
|
|
68
|
+
/** Optional per-bucket analytics event name */
|
|
69
|
+
reporting_event?: string;
|
|
70
|
+
/** URL params to inject when injectUrlParams is enabled */
|
|
71
|
+
url_params?: Record<string, string>;
|
|
72
|
+
/** Arbitrary key-value pairs for analytics adapters */
|
|
73
|
+
reporting_params?: Record<string, string>;
|
|
60
74
|
}
|
|
61
75
|
/**
|
|
62
76
|
* Cookie structure for A/B test assignments.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,qFAAqF;IACrF,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,oDAAoD;IACpD,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAEzC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAExB;;;OAGG;IACH,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACxB"}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import type { AbTest, IBlobStore } from '../types';
|
|
1
|
+
import type { AbTest, AbTestVariantConfig, IBlobStore } from '../types';
|
|
2
|
+
/** Legacy CMS configuration shape accepted during migration. */
|
|
3
|
+
interface LegacyVariantConfig {
|
|
4
|
+
weight: number;
|
|
5
|
+
variant_label?: string;
|
|
6
|
+
reporting_event?: string;
|
|
7
|
+
hubspot_event_name?: string;
|
|
8
|
+
utm_content?: string;
|
|
9
|
+
url_params?: Record<string, string>;
|
|
10
|
+
reporting_params?: Record<string, string>;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Raw PageTest data from Contentful (before transformation).
|
|
4
14
|
* This interface represents the expected shape of data from your Contentful fetch.
|
|
@@ -16,11 +26,10 @@ export interface RawPageTest {
|
|
|
16
26
|
trackingLabel?: string | null;
|
|
17
27
|
/** Optional search parameters to match */
|
|
18
28
|
searchParameters?: string | null;
|
|
29
|
+
/** When true, inject url_params from the assigned bucket */
|
|
30
|
+
injectUrlParams?: boolean | null;
|
|
19
31
|
/** Variant configuration JSON */
|
|
20
|
-
configuration?:
|
|
21
|
-
weight: number;
|
|
22
|
-
hubspot_event_name?: string;
|
|
23
|
-
}> | null;
|
|
32
|
+
configuration?: LegacyVariantConfig[] | null;
|
|
24
33
|
/** Control page reference */
|
|
25
34
|
control?: {
|
|
26
35
|
sys?: {
|
|
@@ -77,6 +86,10 @@ export interface WebhookResult {
|
|
|
77
86
|
/** Optional error message */
|
|
78
87
|
error?: string;
|
|
79
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Normalize a single bucket config, accepting legacy field names.
|
|
91
|
+
*/
|
|
92
|
+
export declare function normalizeVariantConfig(raw: LegacyVariantConfig): AbTestVariantConfig;
|
|
80
93
|
/**
|
|
81
94
|
* Transform raw Contentful PageTest data into AbTest format.
|
|
82
95
|
*/
|
|
@@ -90,27 +103,7 @@ export declare function transformPageTest(raw: RawPageTest, onSkipped?: (testId:
|
|
|
90
103
|
export declare function processAbTestWebhook(config: WebhookHandlerConfig): Promise<WebhookResult>;
|
|
91
104
|
/**
|
|
92
105
|
* Create a Next.js API route handler for the A/B test webhook.
|
|
93
|
-
*
|
|
94
|
-
* @param config - Webhook handler configuration
|
|
95
|
-
* @returns POST handler function
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* // app/api/webhooks/ab-test/route.ts
|
|
100
|
-
* import { createWebhookHandler } from '@se-studio/ab-testing/webhook';
|
|
101
|
-
* import { getAbTestStore } from '@/server/abTestStore';
|
|
102
|
-
* import { fetchAllPageTests } from '@/cms/pageTests';
|
|
103
|
-
* import { revalidateTag } from 'next/cache';
|
|
104
|
-
*
|
|
105
|
-
* export const dynamic = 'force-dynamic';
|
|
106
|
-
*
|
|
107
|
-
* export const POST = createWebhookHandler({
|
|
108
|
-
* fetchPageTests: () => fetchAllPageTests(false), // preview=false
|
|
109
|
-
* getStore: getAbTestStore,
|
|
110
|
-
* webhookSecret: process.env.CONTENTFUL_WEBHOOK_SECRET,
|
|
111
|
-
* revalidate: () => revalidateTag('PageTests'),
|
|
112
|
-
* });
|
|
113
|
-
* ```
|
|
114
106
|
*/
|
|
115
107
|
export declare function createWebhookHandler(config: WebhookHandlerConfig): (request: Request) => Promise<Response>;
|
|
108
|
+
export {};
|
|
116
109
|
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/webhook/handler.js
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a single bucket config, accepting legacy field names.
|
|
3
|
+
*/
|
|
4
|
+
export function normalizeVariantConfig(raw) {
|
|
5
|
+
const reporting_event = raw.reporting_event ?? raw.hubspot_event_name;
|
|
6
|
+
const url_params = raw.url_params ??
|
|
7
|
+
(raw.utm_content !== undefined ? { utm_content: raw.utm_content } : undefined);
|
|
8
|
+
const config = {
|
|
9
|
+
weight: raw.weight,
|
|
10
|
+
};
|
|
11
|
+
if (raw.variant_label) {
|
|
12
|
+
config.variant_label = raw.variant_label;
|
|
13
|
+
}
|
|
14
|
+
if (reporting_event) {
|
|
15
|
+
config.reporting_event = reporting_event;
|
|
16
|
+
}
|
|
17
|
+
if (url_params && Object.keys(url_params).length > 0) {
|
|
18
|
+
config.url_params = url_params;
|
|
19
|
+
}
|
|
20
|
+
if (raw.reporting_params && Object.keys(raw.reporting_params).length > 0) {
|
|
21
|
+
config.reporting_params = raw.reporting_params;
|
|
22
|
+
}
|
|
23
|
+
return config;
|
|
24
|
+
}
|
|
1
25
|
/**
|
|
2
26
|
* Transform raw Contentful PageTest data into AbTest format.
|
|
3
27
|
*/
|
|
@@ -13,6 +37,7 @@ export function transformPageTest(raw, onSkipped) {
|
|
|
13
37
|
id: item.sys.id,
|
|
14
38
|
slug: item.slug,
|
|
15
39
|
}));
|
|
40
|
+
const configuration = (raw.configuration ?? []).map(normalizeVariantConfig);
|
|
16
41
|
return {
|
|
17
42
|
id: raw.sys.id,
|
|
18
43
|
cmsLabel: raw.cmsLabel || '',
|
|
@@ -20,7 +45,8 @@ export function transformPageTest(raw, onSkipped) {
|
|
|
20
45
|
searchParameters: raw.searchParameters ?? undefined,
|
|
21
46
|
trackingLabel: raw.trackingLabel ?? undefined,
|
|
22
47
|
enabled: raw.enabled ?? false,
|
|
23
|
-
|
|
48
|
+
injectUrlParams: raw.injectUrlParams ?? false,
|
|
49
|
+
configuration,
|
|
24
50
|
variants,
|
|
25
51
|
};
|
|
26
52
|
}
|
|
@@ -67,27 +93,6 @@ export async function processAbTestWebhook(config) {
|
|
|
67
93
|
}
|
|
68
94
|
/**
|
|
69
95
|
* Create a Next.js API route handler for the A/B test webhook.
|
|
70
|
-
*
|
|
71
|
-
* @param config - Webhook handler configuration
|
|
72
|
-
* @returns POST handler function
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* // app/api/webhooks/ab-test/route.ts
|
|
77
|
-
* import { createWebhookHandler } from '@se-studio/ab-testing/webhook';
|
|
78
|
-
* import { getAbTestStore } from '@/server/abTestStore';
|
|
79
|
-
* import { fetchAllPageTests } from '@/cms/pageTests';
|
|
80
|
-
* import { revalidateTag } from 'next/cache';
|
|
81
|
-
*
|
|
82
|
-
* export const dynamic = 'force-dynamic';
|
|
83
|
-
*
|
|
84
|
-
* export const POST = createWebhookHandler({
|
|
85
|
-
* fetchPageTests: () => fetchAllPageTests(false), // preview=false
|
|
86
|
-
* getStore: getAbTestStore,
|
|
87
|
-
* webhookSecret: process.env.CONTENTFUL_WEBHOOK_SECRET,
|
|
88
|
-
* revalidate: () => revalidateTag('PageTests'),
|
|
89
|
-
* });
|
|
90
|
-
* ```
|
|
91
96
|
*/
|
|
92
97
|
export function createWebhookHandler(config) {
|
|
93
98
|
return async function handler(request) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/webhook/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Utilities for processing Contentful webhooks to sync PageTest configurations.
|
|
5
5
|
*/
|
|
6
6
|
export type { RawPageTest, WebhookHandlerConfig, WebhookResult, } from './handler';
|
|
7
|
-
export { createWebhookHandler, processAbTestWebhook, transformPageTest, } from './handler';
|
|
7
|
+
export { createWebhookHandler, normalizeVariantConfig, processAbTestWebhook, transformPageTest, } from './handler';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
|
package/dist/webhook/index.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Utilities for processing Contentful webhooks to sync PageTest configurations.
|
|
5
5
|
*/
|
|
6
|
-
export { createWebhookHandler, processAbTestWebhook, transformPageTest, } from './handler';
|
|
6
|
+
export { createWebhookHandler, normalizeVariantConfig, processAbTestWebhook, transformPageTest, } from './handler';
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@se-studio/ab-testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Server-side A/B testing framework for Next.js applications with Contentful CMS",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"./components": {
|
|
36
36
|
"types": "./dist/components/index.d.ts",
|
|
37
37
|
"import": "./dist/components/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./reporting": {
|
|
40
|
+
"types": "./dist/reporting/buildExperimentImpression.d.ts",
|
|
41
|
+
"import": "./dist/reporting/buildExperimentImpression.js"
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
"bin": {
|
|
@@ -73,12 +77,14 @@
|
|
|
73
77
|
"@types/react": "^19.2.17",
|
|
74
78
|
"next": "^15.5.20",
|
|
75
79
|
"typescript": "^6.0.3",
|
|
80
|
+
"vitest": "^4.1.9",
|
|
76
81
|
"@se-studio/core-ui": "1.14.2"
|
|
77
82
|
},
|
|
78
83
|
"scripts": {
|
|
79
84
|
"build": "tsc --project tsconfig.build.json",
|
|
80
85
|
"dev": "tsc --project tsconfig.build.json --watch",
|
|
81
86
|
"type-check": "tsc --noEmit",
|
|
87
|
+
"test": "vitest run",
|
|
82
88
|
"lint": "biome lint .",
|
|
83
89
|
"clean": "rm -rf dist .turbo *.tsbuildinfo"
|
|
84
90
|
}
|