@uniformdev/insights 20.35.1-alpha.87

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/LICENSE.txt ADDED
@@ -0,0 +1,2 @@
1
+ © 2025 Uniform Systems, Inc. All Rights Reserved.
2
+ See details of Uniform Systems, Inc. Master Subscription Agreement here: https://uniform.dev/eula
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @uniformdev/insights
2
+
3
+ This package provides insights tracking capabilities for Uniform Context, including a proxy handler for forwarding analytics requests.
4
+
5
+ ## Client-side tracking
6
+
7
+ Create Uniform Insights Context plugin with endpoint type `api`.
8
+
9
+ ```
10
+ import {
11
+ Context,
12
+ ContextPlugin,
13
+ enableContextDevTools,
14
+ enableDebugConsoleLogDrain,
15
+ ManifestV2,
16
+ } from '@uniformdev/context';
17
+ import { enableUniformInsights } from '@uniformdev/insights';
18
+
19
+ const plugins: ContextPlugin[] = [];
20
+
21
+ if (typeof window !== 'undefined' && window.document) {
22
+ plugins.push(
23
+ enableUniformInsights({
24
+ endpoint: {
25
+ type: 'api',
26
+ projectId: process.env.NEXT_PUBLIC_PROJECT_ID!,
27
+ apiKey: process.env.NEXT_PUBLIC_UNIFORM_INSIGHTS_KEY!,
28
+ host: process.env.NEXT_PUBLIC_INSIGHTS_API_URL!,
29
+ },
30
+ })
31
+ );
32
+ }
33
+
34
+ const context = new Context({
35
+ ...
36
+ plugins: plugins,
37
+ });
38
+ ```
39
+
40
+ ## Proxy Handler
41
+
42
+ The proxy handler is optimized for Node.js environments and provides a simple interface for forwarding analytics data to the Uniform Insights API. It automatically:
43
+
44
+ - Routes requests to `/v0/events` endpoint
45
+ - Sets proper authentication headers
46
+ - Configures NDJSON content type
47
+ - Uses Node.js fetch API types
48
+ - Only requires the request body (URL and headers are built from config)
49
+
50
+ ### Basic Usage with Next.JS
51
+
52
+ ```typescript
53
+ import { NextApiRequest, NextApiResponse } from 'next';
54
+ import { BackendInsightsProxyHandler } from '@uniformdev/insights/proxy';
55
+
56
+ // Create a proxy handler
57
+ const proxyHandler = new BackendInsightsProxyHandler({
58
+ apiHost: process.env.INSIGHTS_API_URL,
59
+ apiKey: process.env.INSIGHTS_API_KEY,
60
+ });
61
+
62
+ export default async function handler(req: NextApiRequest, res: NextApiResponse) {
63
+ const proxyResponse = await proxyHandler.handleRequest(req.body);
64
+
65
+ res.status(proxyResponse.status).json(proxyResponse.body);
66
+ }
67
+ ```
68
+ To use proxy mode you have to change you Context plugin settings a bit:
69
+
70
+ ```
71
+ enableUniformInsights({
72
+ endpoint: {
73
+ type: 'proxy',
74
+ projectId: process.env.UNIFORM_PROJECT_ID!,
75
+ path: '/api/{YOUR_ENDPOINT},
76
+ },
77
+ })
78
+ ```
@@ -0,0 +1,38 @@
1
+ // src/proxy.ts
2
+ var BackendInsightsProxyHandler = class {
3
+ constructor(config) {
4
+ this.config = config;
5
+ }
6
+ /**
7
+ * Handle a proxy request with only the body payload
8
+ * @param body - The request body to forward
9
+ * @returns Promise resolving to the API response
10
+ */
11
+ async handleRequest(originalBody) {
12
+ try {
13
+ const targetUrl = new URL("/v0/events", this.config.apiHost);
14
+ targetUrl.searchParams.set("name", "events");
15
+ return fetch(targetUrl.toString(), {
16
+ method: "POST",
17
+ headers: {
18
+ Authorization: `Bearer ${this.config.apiKey}`,
19
+ "Content-Type": "application/x-ndjson",
20
+ Accept: "application/json"
21
+ },
22
+ body: originalBody
23
+ });
24
+ } catch (error) {
25
+ throw new Error(
26
+ `Backend proxy request failed: ${error instanceof Error ? error.message : "Unknown error"}`
27
+ );
28
+ }
29
+ }
30
+ };
31
+ function createBackendInsightsProxyHandler(config) {
32
+ return new BackendInsightsProxyHandler(config);
33
+ }
34
+
35
+ export {
36
+ BackendInsightsProxyHandler,
37
+ createBackendInsightsProxyHandler
38
+ };
@@ -0,0 +1,125 @@
1
+ import { TestEvent, Context, PersonalizationEvent, ContextPlugin } from '@uniformdev/context';
2
+ export { BackendInsightsProxyHandler, BackendProxyConfig, createBackendInsightsProxyHandler } from './proxy.mjs';
3
+
4
+ type InsightsEndpoint = {
5
+ /** Sending events directly to Uniform Insights API from client-side */
6
+ type: 'api';
7
+ /** Region aware api endpoint. Can be one of two values:
8
+ * - https://analytics.uniform.global
9
+ * - https://analytics.eu.uniform.global
10
+ *
11
+ * Otherwise it will come as NEXT_PUBLIC_INSIGHTS_API_URL environment variable copied from Insights Settings page
12
+ */
13
+ host: string;
14
+ /** API key for the Uniform Insights API. Can be found in Insights Settings page */
15
+ apiKey: string;
16
+ /** Uniform project Id. */
17
+ projectId: string;
18
+ } | {
19
+ /** Sending events through own proxy. Useful to avoid any traffic towards external analytics related endpoints to trigger AD blockers */
20
+ type: 'proxy';
21
+ /** Path to internal proxy endpoint. */
22
+ path: string;
23
+ /** Uniform project Id. */
24
+ projectId: string;
25
+ };
26
+ type InsightsStorage = {
27
+ get: () => InsightsStorageData | undefined;
28
+ set: (data: Omit<InsightsStorageData, 'updated'>) => void;
29
+ clear: () => void;
30
+ };
31
+ type InsightsStorageData = {
32
+ visitorId: string;
33
+ sessionId: string;
34
+ updated: number;
35
+ };
36
+ type UniformMetadata = {
37
+ composition_id?: string;
38
+ pm_node_path?: string;
39
+ dynamic_inputs?: Record<string, string>;
40
+ };
41
+ type WebMetadata = {
42
+ 'user-agent': string;
43
+ locale: string;
44
+ location: string;
45
+ referrer: string;
46
+ pathname: string;
47
+ href: string;
48
+ };
49
+ type InsightsTrackingEvent<TAction extends string, TPayload = Record<string, never>> = {
50
+ timestamp: string;
51
+ action: TAction;
52
+ version: '2';
53
+ visitor_id: string;
54
+ session_id: string;
55
+ page_view_id: string;
56
+ project_id: string;
57
+ payload: TPayload;
58
+ web_metadata: WebMetadata;
59
+ uniform: UniformMetadata;
60
+ };
61
+ type PageHitPayload = Record<string, never>;
62
+ type SessionStatePayload = {
63
+ previous_session_id: string | undefined;
64
+ };
65
+ type TestResultPayload = TestEvent;
66
+ type PersonalizationResultPayload = {
67
+ name: string;
68
+ variantId: string;
69
+ control: boolean | undefined;
70
+ changed: boolean;
71
+ };
72
+ type GoalConvertPayload = {
73
+ goal_id: string;
74
+ };
75
+ type PageHitEvent = InsightsTrackingEvent<'page_hit', PageHitPayload>;
76
+ type SessionStateEvent = InsightsTrackingEvent<'session_start', SessionStatePayload>;
77
+ type TestResultEvent = InsightsTrackingEvent<'test_result', TestResultPayload>;
78
+ type PersonalizationResultEvent = InsightsTrackingEvent<'personalization_result', PersonalizationResultPayload>;
79
+ type GoalConvertEvent = InsightsTrackingEvent<'goal_convert', GoalConvertPayload>;
80
+ type UniformInsights = {
81
+ init: (context: Context) => Promise<void>;
82
+ forget: () => void;
83
+ pageHit: (compositionData?: UniformMetadata) => void;
84
+ testResult: (result: TestEvent, compositionData?: UniformMetadata) => void;
85
+ personalizationResult: (result: PersonalizationEvent, compositionData?: UniformMetadata) => void;
86
+ goalConvert: (goalId: string, compositionData?: UniformMetadata) => void;
87
+ get sessionId(): string | undefined;
88
+ };
89
+
90
+ type BatchConfig = {
91
+ maxBatchSize: number;
92
+ maxBatchDelayMs: number;
93
+ maxPayloadSizeBytes: number;
94
+ maxRequestsPerSecond: number;
95
+ };
96
+
97
+ interface InsightsPluginOptions {
98
+ endpoint: InsightsEndpoint;
99
+ /** Custom storage implementation (optional, defaults to localStorage) */
100
+ storage?: InsightsStorage;
101
+ /** Batch configuration for event processing (optional, batching disabled by default) */
102
+ batchConfig?: Partial<BatchConfig>;
103
+ /** Session duration in seconds (default: 30 minutes) */
104
+ sessionDurationSeconds?: number;
105
+ /** Async functions for visitor and session ID generation */
106
+ getVisitorId?: ({ context, previousVisitorId, previousSessionId, }: {
107
+ context: Context;
108
+ previousVisitorId?: string;
109
+ previousSessionId?: string;
110
+ }) => Promise<string>;
111
+ getSessionId?: ({ context, visitorId, previousSessionId, }: {
112
+ context: Context;
113
+ visitorId: string;
114
+ previousSessionId?: string;
115
+ }) => Promise<string>;
116
+ }
117
+ declare const createInsightsPlugin: (options: InsightsPluginOptions) => ContextPlugin;
118
+
119
+ declare const createInsightsStorage: (customStorage?: InsightsStorage) => InsightsStorage;
120
+ /**
121
+ * Creates a memory-based storage implementation for server-side or testing environments
122
+ */
123
+ declare const createMemoryStorage: () => InsightsStorage;
124
+
125
+ export { type BatchConfig, type GoalConvertEvent, type GoalConvertPayload, type InsightsEndpoint, type InsightsPluginOptions, type InsightsStorage, type InsightsStorageData, type InsightsTrackingEvent, type PageHitEvent, type PageHitPayload, type PersonalizationResultEvent, type PersonalizationResultPayload, type SessionStateEvent, type SessionStatePayload, type TestResultEvent, type TestResultPayload, type UniformInsights, type UniformMetadata, type WebMetadata, createInsightsPlugin, createInsightsStorage, createMemoryStorage, createInsightsPlugin as enableUniformInsights };
@@ -0,0 +1,125 @@
1
+ import { TestEvent, Context, PersonalizationEvent, ContextPlugin } from '@uniformdev/context';
2
+ export { BackendInsightsProxyHandler, BackendProxyConfig, createBackendInsightsProxyHandler } from './proxy.js';
3
+
4
+ type InsightsEndpoint = {
5
+ /** Sending events directly to Uniform Insights API from client-side */
6
+ type: 'api';
7
+ /** Region aware api endpoint. Can be one of two values:
8
+ * - https://analytics.uniform.global
9
+ * - https://analytics.eu.uniform.global
10
+ *
11
+ * Otherwise it will come as NEXT_PUBLIC_INSIGHTS_API_URL environment variable copied from Insights Settings page
12
+ */
13
+ host: string;
14
+ /** API key for the Uniform Insights API. Can be found in Insights Settings page */
15
+ apiKey: string;
16
+ /** Uniform project Id. */
17
+ projectId: string;
18
+ } | {
19
+ /** Sending events through own proxy. Useful to avoid any traffic towards external analytics related endpoints to trigger AD blockers */
20
+ type: 'proxy';
21
+ /** Path to internal proxy endpoint. */
22
+ path: string;
23
+ /** Uniform project Id. */
24
+ projectId: string;
25
+ };
26
+ type InsightsStorage = {
27
+ get: () => InsightsStorageData | undefined;
28
+ set: (data: Omit<InsightsStorageData, 'updated'>) => void;
29
+ clear: () => void;
30
+ };
31
+ type InsightsStorageData = {
32
+ visitorId: string;
33
+ sessionId: string;
34
+ updated: number;
35
+ };
36
+ type UniformMetadata = {
37
+ composition_id?: string;
38
+ pm_node_path?: string;
39
+ dynamic_inputs?: Record<string, string>;
40
+ };
41
+ type WebMetadata = {
42
+ 'user-agent': string;
43
+ locale: string;
44
+ location: string;
45
+ referrer: string;
46
+ pathname: string;
47
+ href: string;
48
+ };
49
+ type InsightsTrackingEvent<TAction extends string, TPayload = Record<string, never>> = {
50
+ timestamp: string;
51
+ action: TAction;
52
+ version: '2';
53
+ visitor_id: string;
54
+ session_id: string;
55
+ page_view_id: string;
56
+ project_id: string;
57
+ payload: TPayload;
58
+ web_metadata: WebMetadata;
59
+ uniform: UniformMetadata;
60
+ };
61
+ type PageHitPayload = Record<string, never>;
62
+ type SessionStatePayload = {
63
+ previous_session_id: string | undefined;
64
+ };
65
+ type TestResultPayload = TestEvent;
66
+ type PersonalizationResultPayload = {
67
+ name: string;
68
+ variantId: string;
69
+ control: boolean | undefined;
70
+ changed: boolean;
71
+ };
72
+ type GoalConvertPayload = {
73
+ goal_id: string;
74
+ };
75
+ type PageHitEvent = InsightsTrackingEvent<'page_hit', PageHitPayload>;
76
+ type SessionStateEvent = InsightsTrackingEvent<'session_start', SessionStatePayload>;
77
+ type TestResultEvent = InsightsTrackingEvent<'test_result', TestResultPayload>;
78
+ type PersonalizationResultEvent = InsightsTrackingEvent<'personalization_result', PersonalizationResultPayload>;
79
+ type GoalConvertEvent = InsightsTrackingEvent<'goal_convert', GoalConvertPayload>;
80
+ type UniformInsights = {
81
+ init: (context: Context) => Promise<void>;
82
+ forget: () => void;
83
+ pageHit: (compositionData?: UniformMetadata) => void;
84
+ testResult: (result: TestEvent, compositionData?: UniformMetadata) => void;
85
+ personalizationResult: (result: PersonalizationEvent, compositionData?: UniformMetadata) => void;
86
+ goalConvert: (goalId: string, compositionData?: UniformMetadata) => void;
87
+ get sessionId(): string | undefined;
88
+ };
89
+
90
+ type BatchConfig = {
91
+ maxBatchSize: number;
92
+ maxBatchDelayMs: number;
93
+ maxPayloadSizeBytes: number;
94
+ maxRequestsPerSecond: number;
95
+ };
96
+
97
+ interface InsightsPluginOptions {
98
+ endpoint: InsightsEndpoint;
99
+ /** Custom storage implementation (optional, defaults to localStorage) */
100
+ storage?: InsightsStorage;
101
+ /** Batch configuration for event processing (optional, batching disabled by default) */
102
+ batchConfig?: Partial<BatchConfig>;
103
+ /** Session duration in seconds (default: 30 minutes) */
104
+ sessionDurationSeconds?: number;
105
+ /** Async functions for visitor and session ID generation */
106
+ getVisitorId?: ({ context, previousVisitorId, previousSessionId, }: {
107
+ context: Context;
108
+ previousVisitorId?: string;
109
+ previousSessionId?: string;
110
+ }) => Promise<string>;
111
+ getSessionId?: ({ context, visitorId, previousSessionId, }: {
112
+ context: Context;
113
+ visitorId: string;
114
+ previousSessionId?: string;
115
+ }) => Promise<string>;
116
+ }
117
+ declare const createInsightsPlugin: (options: InsightsPluginOptions) => ContextPlugin;
118
+
119
+ declare const createInsightsStorage: (customStorage?: InsightsStorage) => InsightsStorage;
120
+ /**
121
+ * Creates a memory-based storage implementation for server-side or testing environments
122
+ */
123
+ declare const createMemoryStorage: () => InsightsStorage;
124
+
125
+ export { type BatchConfig, type GoalConvertEvent, type GoalConvertPayload, type InsightsEndpoint, type InsightsPluginOptions, type InsightsStorage, type InsightsStorageData, type InsightsTrackingEvent, type PageHitEvent, type PageHitPayload, type PersonalizationResultEvent, type PersonalizationResultPayload, type SessionStateEvent, type SessionStatePayload, type TestResultEvent, type TestResultPayload, type UniformInsights, type UniformMetadata, type WebMetadata, createInsightsPlugin, createInsightsStorage, createMemoryStorage, createInsightsPlugin as enableUniformInsights };