@ninetailed/experience.js-plugin-analytics
Advanced tools
+58
-7
@@ -9,3 +9,12 @@ 'use strict'; | ||
| const ElementSeenPayloadSchema = zod.z.object({ | ||
| // Base schema with shared properties | ||
| const BaseSeenPayloadSchema = zod.z.object({ | ||
| componentType: zod.z.union([zod.z.literal('Entry'), zod.z.literal('Variable')]), | ||
| variant: zod.z.object({ | ||
| id: zod.z.string() | ||
| }).catchall(zod.z.unknown()), | ||
| variantIndex: zod.z.number() | ||
| }); | ||
| // Element specific schema | ||
| const ElementSeenPayloadSchema = BaseSeenPayloadSchema.extend({ | ||
| element: zod.z.any(), | ||
@@ -28,8 +37,9 @@ experience: zod.z.object({ | ||
| }), | ||
| variant: zod.z.object({ | ||
| id: zod.z.string() | ||
| }).catchall(zod.z.unknown()), | ||
| variantIndex: zod.z.number(), | ||
| seenFor: zod.z.number().optional().default(0) | ||
| }); | ||
| // Variable specific schema | ||
| const VariableSeenPayloadSchema = BaseSeenPayloadSchema.extend({ | ||
| variable: experience_jsShared.SerializableObject, | ||
| experienceId: zod.z.string().optional() | ||
| }); | ||
@@ -49,4 +59,5 @@ const TrackComponentPropertiesSchema = zod.z.object({ | ||
| const HAS_SEEN_ELEMENT = 'has_seen_element'; | ||
| const HAS_SEEN_VARIABLE = 'has_seen_variable'; | ||
| var _a$1; | ||
| var _a$1, _b; | ||
| class NinetailedPlugin { | ||
@@ -61,4 +72,9 @@ constructor() { | ||
| }; | ||
| this[_b] = event => { | ||
| this.onHasSeenVariable(event); | ||
| }; | ||
| // eslint-disable-next-line @typescript-eslint/no-empty-function | ||
| this.onHasSeenElement = () => {}; | ||
| // eslint-disable-next-line @typescript-eslint/no-empty-function | ||
| this.onHasSeenVariable = () => {}; | ||
| this.setComponentViewTrackingThreshold = threshold => { | ||
@@ -70,3 +86,3 @@ this.componentViewTrackingThreshold = threshold; | ||
| } | ||
| _a$1 = HAS_SEEN_ELEMENT; | ||
| _a$1 = HAS_SEEN_ELEMENT, _b = HAS_SEEN_VARIABLE; | ||
@@ -82,2 +98,3 @@ var _a; | ||
| this.seenElements = new WeakMap(); | ||
| this.seenVariables = new Map(); | ||
| this.getHasSeenExperienceEventPayload = data => { | ||
@@ -123,2 +140,3 @@ const event = Object.entries(this.hasSeenExperienceEventTemplate).reduce((acc, [keyTemplate, valueTemplate]) => { | ||
| audience: sanitizedPayload.data.audience, | ||
| componentType: sanitizedPayload.data.componentType, | ||
| selectedVariant: sanitizedPayload.data.variant, | ||
@@ -137,2 +155,33 @@ selectedVariantIndex: sanitizedPayload.data.variantIndex, | ||
| }; | ||
| this.onHasSeenVariable = ({ | ||
| payload | ||
| }) => { | ||
| const sanitizedPayload = VariableSeenPayloadSchema.safeParse(payload); | ||
| if (!sanitizedPayload.success) { | ||
| experience_jsShared.logger.error('Invalid payload for has_seen_variable event', sanitizedPayload.error.format()); | ||
| return; | ||
| } | ||
| const componentId = sanitizedPayload.data.variant.id; | ||
| if (typeof componentId === 'undefined') { | ||
| experience_jsShared.logger.error('Component ID is undefined in has_seen_variable event payload'); | ||
| return; | ||
| } | ||
| const variableKey = componentId; | ||
| const variablePayloads = this.seenVariables.get(variableKey) || []; | ||
| const selectedVariantSelector = sanitizedPayload.data.variantIndex === 0 ? 'control' : `variant ${sanitizedPayload.data.variantIndex}`; | ||
| const sanitizedTrackVariableProperties = { | ||
| componentId, | ||
| componentType: sanitizedPayload.data.componentType, | ||
| selectedVariant: sanitizedPayload.data.variant, | ||
| selectedVariantIndex: sanitizedPayload.data.variantIndex, | ||
| selectedVariantSelector | ||
| }; | ||
| const isVariableAlreadySeenWithPayload = variablePayloads.some(variablePayload => { | ||
| return radash.isEqual(variablePayload, sanitizedTrackVariableProperties); | ||
| }); | ||
| if (isVariableAlreadySeenWithPayload) { | ||
| return; | ||
| } | ||
| this.seenVariables.set(variableKey, [...variablePayloads, sanitizedTrackVariableProperties]); | ||
| }; | ||
| /** | ||
@@ -163,5 +212,7 @@ * @deprecated | ||
| exports.HAS_SEEN_ELEMENT_START = HAS_SEEN_ELEMENT_START; | ||
| exports.HAS_SEEN_VARIABLE = HAS_SEEN_VARIABLE; | ||
| exports.NinetailedAnalyticsPlugin = NinetailedAnalyticsPlugin; | ||
| exports.NinetailedPlugin = NinetailedPlugin; | ||
| exports.TrackComponentPropertiesSchema = TrackComponentPropertiesSchema; | ||
| exports.VariableSeenPayloadSchema = VariableSeenPayloadSchema; | ||
| exports.hasComponentViewTrackingThreshold = hasComponentViewTrackingThreshold; |
+57
-7
| import { isEqual } from 'radash'; | ||
| import { logger, template } from '@ninetailed/experience.js-shared'; | ||
| import { SerializableObject, logger, template } from '@ninetailed/experience.js-shared'; | ||
| import { z } from 'zod'; | ||
| const ElementSeenPayloadSchema = z.object({ | ||
| // Base schema with shared properties | ||
| const BaseSeenPayloadSchema = z.object({ | ||
| componentType: z.union([z.literal('Entry'), z.literal('Variable')]), | ||
| variant: z.object({ | ||
| id: z.string() | ||
| }).catchall(z.unknown()), | ||
| variantIndex: z.number() | ||
| }); | ||
| // Element specific schema | ||
| const ElementSeenPayloadSchema = BaseSeenPayloadSchema.extend({ | ||
| element: z.any(), | ||
@@ -23,8 +33,9 @@ experience: z.object({ | ||
| }), | ||
| variant: z.object({ | ||
| id: z.string() | ||
| }).catchall(z.unknown()), | ||
| variantIndex: z.number(), | ||
| seenFor: z.number().optional().default(0) | ||
| }); | ||
| // Variable specific schema | ||
| const VariableSeenPayloadSchema = BaseSeenPayloadSchema.extend({ | ||
| variable: SerializableObject, | ||
| experienceId: z.string().optional() | ||
| }); | ||
@@ -44,2 +55,3 @@ const TrackComponentPropertiesSchema = z.object({ | ||
| const HAS_SEEN_ELEMENT = 'has_seen_element'; | ||
| const HAS_SEEN_VARIABLE = 'has_seen_variable'; | ||
@@ -55,4 +67,9 @@ class NinetailedPlugin { | ||
| }; | ||
| this[HAS_SEEN_VARIABLE] = event => { | ||
| this.onHasSeenVariable(event); | ||
| }; | ||
| // eslint-disable-next-line @typescript-eslint/no-empty-function | ||
| this.onHasSeenElement = () => {}; | ||
| // eslint-disable-next-line @typescript-eslint/no-empty-function | ||
| this.onHasSeenVariable = () => {}; | ||
| this.setComponentViewTrackingThreshold = threshold => { | ||
@@ -72,2 +89,3 @@ this.componentViewTrackingThreshold = threshold; | ||
| this.seenElements = new WeakMap(); | ||
| this.seenVariables = new Map(); | ||
| this.getHasSeenExperienceEventPayload = data => { | ||
@@ -113,2 +131,3 @@ const event = Object.entries(this.hasSeenExperienceEventTemplate).reduce((acc, [keyTemplate, valueTemplate]) => { | ||
| audience: sanitizedPayload.data.audience, | ||
| componentType: sanitizedPayload.data.componentType, | ||
| selectedVariant: sanitizedPayload.data.variant, | ||
@@ -127,2 +146,33 @@ selectedVariantIndex: sanitizedPayload.data.variantIndex, | ||
| }; | ||
| this.onHasSeenVariable = ({ | ||
| payload | ||
| }) => { | ||
| const sanitizedPayload = VariableSeenPayloadSchema.safeParse(payload); | ||
| if (!sanitizedPayload.success) { | ||
| logger.error('Invalid payload for has_seen_variable event', sanitizedPayload.error.format()); | ||
| return; | ||
| } | ||
| const componentId = sanitizedPayload.data.variant.id; | ||
| if (typeof componentId === 'undefined') { | ||
| logger.error('Component ID is undefined in has_seen_variable event payload'); | ||
| return; | ||
| } | ||
| const variableKey = componentId; | ||
| const variablePayloads = this.seenVariables.get(variableKey) || []; | ||
| const selectedVariantSelector = sanitizedPayload.data.variantIndex === 0 ? 'control' : `variant ${sanitizedPayload.data.variantIndex}`; | ||
| const sanitizedTrackVariableProperties = { | ||
| componentId, | ||
| componentType: sanitizedPayload.data.componentType, | ||
| selectedVariant: sanitizedPayload.data.variant, | ||
| selectedVariantIndex: sanitizedPayload.data.variantIndex, | ||
| selectedVariantSelector | ||
| }; | ||
| const isVariableAlreadySeenWithPayload = variablePayloads.some(variablePayload => { | ||
| return isEqual(variablePayload, sanitizedTrackVariableProperties); | ||
| }); | ||
| if (isVariableAlreadySeenWithPayload) { | ||
| return; | ||
| } | ||
| this.seenVariables.set(variableKey, [...variablePayloads, sanitizedTrackVariableProperties]); | ||
| }; | ||
| /** | ||
@@ -149,2 +199,2 @@ * @deprecated | ||
| export { ElementSeenPayloadSchema, HAS_SEEN_COMPONENT, HAS_SEEN_ELEMENT, HAS_SEEN_ELEMENT_START, NinetailedAnalyticsPlugin, NinetailedPlugin, TrackComponentPropertiesSchema, hasComponentViewTrackingThreshold }; | ||
| export { ElementSeenPayloadSchema, HAS_SEEN_COMPONENT, HAS_SEEN_ELEMENT, HAS_SEEN_ELEMENT_START, HAS_SEEN_VARIABLE, NinetailedAnalyticsPlugin, NinetailedPlugin, TrackComponentPropertiesSchema, VariableSeenPayloadSchema, hasComponentViewTrackingThreshold }; |
+2
-2
@@ -5,3 +5,3 @@ { | ||
| "license": "MIT", | ||
| "version": "7.13.0", | ||
| "version": "7.14.0", | ||
| "keywords": [ | ||
@@ -20,3 +20,3 @@ "analytics", | ||
| "@anatine/zod-mock": "3.8.1", | ||
| "@ninetailed/experience.js-shared": "7.13.0", | ||
| "@ninetailed/experience.js-shared": "7.14.0", | ||
| "analytics": "0.8.1", | ||
@@ -23,0 +23,0 @@ "radash": "10.9.0", |
+3
-3
@@ -1,5 +0,5 @@ | ||
| export { NinetailedAnalyticsPlugin, type SanitizedElementSeenPayload, } from './lib/NinetailedAnalyticsPlugin'; | ||
| export { NinetailedAnalyticsPlugin, type SanitizedElementSeenPayload, type SanitizedVariableSeenPayload, } from './lib/NinetailedAnalyticsPlugin'; | ||
| export type { Template } from './lib/NinetailedAnalyticsPlugin'; | ||
| export { ElementSeenPayloadSchema } from './lib/ElementSeenPayload'; | ||
| export type { ElementSeenPayload } from './lib/ElementSeenPayload'; | ||
| export { ElementSeenPayloadSchema, VariableSeenPayloadSchema, } from './lib/ElementSeenPayload'; | ||
| export type { ComponentViewEventComponentType, ElementSeenPayload, VariableSeenPayload, } from './lib/ElementSeenPayload'; | ||
| export { TrackComponentPropertiesSchema } from './lib/TrackingProperties'; | ||
@@ -6,0 +6,0 @@ export type { TrackComponentProperties } from './lib/TrackingProperties'; |
| export declare const HAS_SEEN_COMPONENT = "has_seen_component"; | ||
| export declare const HAS_SEEN_ELEMENT_START = "has_seen_elementStart"; | ||
| export declare const HAS_SEEN_ELEMENT = "has_seen_element"; | ||
| export declare const HAS_SEEN_VARIABLE = "has_seen_variable"; |
@@ -0,3 +1,15 @@ | ||
| import { SerializableObject } from '@ninetailed/experience.js-shared'; | ||
| import { z } from 'zod'; | ||
| export declare const ElementSeenPayloadSchema: z.ZodObject<{ | ||
| export type ComponentViewEventComponentType = 'Entry' | 'Variable'; | ||
| export declare const ElementSeenPayloadSchema: z.ZodObject<z.objectUtil.extendShape<{ | ||
| componentType: z.ZodUnion<[z.ZodLiteral<"Entry">, z.ZodLiteral<"Variable">]>; | ||
| variant: z.ZodObject<{ | ||
| id: z.ZodString; | ||
| }, "strip", z.ZodUnknown, z.objectOutputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">, z.objectInputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">>; | ||
| variantIndex: z.ZodNumber; | ||
| }, { | ||
| element: z.ZodAny; | ||
@@ -11,4 +23,4 @@ experience: z.ZodNullable<z.ZodOptional<z.ZodObject<{ | ||
| }, "strip", z.ZodTypeAny, { | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| id: string; | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| sticky: boolean; | ||
@@ -18,4 +30,4 @@ name?: string | undefined; | ||
| }, { | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| id: string; | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| name?: string | undefined; | ||
@@ -38,17 +50,5 @@ description?: string | undefined; | ||
| }>>>>; | ||
| variant: z.ZodObject<{ | ||
| id: z.ZodString; | ||
| }, "strip", z.ZodUnknown, z.objectOutputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">, z.objectInputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">>; | ||
| variantIndex: z.ZodNumber; | ||
| seenFor: z.ZodDefault<z.ZodOptional<z.ZodNumber>>; | ||
| }, "strip", z.ZodTypeAny, { | ||
| audience: { | ||
| id: string; | ||
| name?: string | undefined; | ||
| description?: string | undefined; | ||
| } | null; | ||
| }>, "strip", z.ZodTypeAny, { | ||
| componentType: "Entry" | "Variable"; | ||
| variant: { | ||
@@ -60,7 +60,12 @@ id: string; | ||
| variantIndex: number; | ||
| audience: { | ||
| id: string; | ||
| name?: string | undefined; | ||
| description?: string | undefined; | ||
| } | null; | ||
| seenFor: number; | ||
| element?: any; | ||
| experience?: { | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| id: string; | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| sticky: boolean; | ||
@@ -71,2 +76,3 @@ name?: string | undefined; | ||
| }, { | ||
| componentType: "Entry" | "Variable"; | ||
| variant: { | ||
@@ -80,4 +86,4 @@ id: string; | ||
| experience?: { | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| id: string; | ||
| type: "nt_experiment" | "nt_personalization"; | ||
| name?: string | undefined; | ||
@@ -97,1 +103,36 @@ description?: string | undefined; | ||
| }; | ||
| export declare const VariableSeenPayloadSchema: z.ZodObject<z.objectUtil.extendShape<{ | ||
| componentType: z.ZodUnion<[z.ZodLiteral<"Entry">, z.ZodLiteral<"Variable">]>; | ||
| variant: z.ZodObject<{ | ||
| id: z.ZodString; | ||
| }, "strip", z.ZodUnknown, z.objectOutputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">, z.objectInputType<{ | ||
| id: z.ZodString; | ||
| }, z.ZodUnknown, "strip">>; | ||
| variantIndex: z.ZodNumber; | ||
| }, { | ||
| variable: z.ZodType<SerializableObject, z.ZodTypeDef, unknown>; | ||
| experienceId: z.ZodOptional<z.ZodString>; | ||
| }>, "strip", z.ZodTypeAny, { | ||
| componentType: "Entry" | "Variable"; | ||
| variant: { | ||
| id: string; | ||
| } & { | ||
| [k: string]: unknown; | ||
| }; | ||
| variantIndex: number; | ||
| variable: SerializableObject; | ||
| experienceId?: string | undefined; | ||
| }, { | ||
| componentType: "Entry" | "Variable"; | ||
| variant: { | ||
| id: string; | ||
| } & { | ||
| [k: string]: unknown; | ||
| }; | ||
| variantIndex: number; | ||
| variable?: unknown; | ||
| experienceId?: string | undefined; | ||
| }>; | ||
| export type VariableSeenPayload = z.input<typeof VariableSeenPayloadSchema>; |
@@ -1,2 +0,2 @@ | ||
| import { type ElementSeenPayload } from './ElementSeenPayload'; | ||
| import { type ElementSeenPayload, type VariableSeenPayload } from './ElementSeenPayload'; | ||
| import { type TrackComponentProperties } from './TrackingProperties'; | ||
@@ -12,6 +12,15 @@ import { EventHandler, NinetailedPlugin } from './NinetailedPlugin'; | ||
| selectedVariantIndex: ElementSeenPayload['variantIndex']; | ||
| componentType: NonNullable<ElementSeenPayload['componentType']>; | ||
| }; | ||
| export type SanitizedVariableSeenPayload = { | ||
| componentId: string; | ||
| componentType: VariableSeenPayload['componentType']; | ||
| selectedVariant: VariableSeenPayload['variant']; | ||
| selectedVariantIndex: VariableSeenPayload['variantIndex']; | ||
| selectedVariantSelector: string; | ||
| }; | ||
| export declare abstract class NinetailedAnalyticsPlugin<THasSeenExperienceEventTemplate extends Template = Template> extends NinetailedPlugin { | ||
| private readonly hasSeenExperienceEventTemplate; | ||
| private seenElements; | ||
| private seenVariables; | ||
| constructor(hasSeenExperienceEventTemplate?: THasSeenExperienceEventTemplate); | ||
@@ -25,2 +34,3 @@ protected abstract onTrackExperience(properties: SanitizedElementSeenPayload, eventPayload: Record<string, string>): Promise<void>; | ||
| onHasSeenElement: EventHandler<ElementSeenPayload>; | ||
| onHasSeenVariable: EventHandler<VariableSeenPayload>; | ||
| /** | ||
@@ -27,0 +37,0 @@ * @deprecated |
| import { AnalyticsPlugin } from 'analytics'; | ||
| import { AnalyticsInstance } from './AnalyticsInstance'; | ||
| import { HasComponentViewTrackingThreshold } from './types/interfaces/HasComponentViewTrackingThreshold'; | ||
| import { ElementSeenPayload } from './ElementSeenPayload'; | ||
| import { HAS_SEEN_ELEMENT } from './constants'; | ||
| import { ElementSeenPayload, VariableSeenPayload } from './ElementSeenPayload'; | ||
| import { HAS_SEEN_ELEMENT, HAS_SEEN_VARIABLE } from './constants'; | ||
| export type EventHandlerParams<T = unknown> = { | ||
@@ -17,5 +17,7 @@ payload: T; | ||
| [HAS_SEEN_ELEMENT]: EventHandler<ElementSeenPayload>; | ||
| [HAS_SEEN_VARIABLE]: EventHandler<VariableSeenPayload>; | ||
| protected onHasSeenElement: EventHandler<ElementSeenPayload>; | ||
| protected onHasSeenVariable: EventHandler<VariableSeenPayload>; | ||
| setComponentViewTrackingThreshold: (threshold: number) => void; | ||
| getComponentViewTrackingThreshold: () => number; | ||
| } |
27094
33.63%640
31.69%+ Added
- Removed