Tracking API

Experiment Tracking

Report exposure to externally managed experiments and attach experiment contexts to interactions.

Experiment tracking is available in @psykhe-ai/browser-plugin-snowplow-ecommerce version 0.2.0 and later. Use trackExperimentExposure to report participation and attach repeatable experiment contexts to ecommerce interactions.

Report exposure when your integration's chosen condition occurs, such as opening a page or reaching 50% scroll. Send it for every variant, including baseline, at the same condition. Support any number of variants and concurrent experiments. Requesting recommendations does not establish exposure: the storefront may later suppress their display.

Install the plugin

Install or upgrade the plugin, then use the tracker configured in Getting Started:

pnpm add @psykhe-ai/browser-plugin-snowplow-ecommerce@^0.2.0

Report an exposure

Supply one entry per experiment involved in the action. The plugin builds the exposure event and experiment contexts. The tracker supplies page, browser, session, time, and event identifiers.

import {
  trackExperimentExposure,
  type Experiment,
} from "@psykhe-ai/browser-plugin-snowplow-ecommerce";

// Supply the decisions when they become available in your integration.
const experiments: Experiment[] = [
  {
    experimentId: "recommendations-2026-10",
    variationId: "baseline",
    custom: [{ key: "placement", value: "product_page" }],
  },
  {
    experimentId: "product-layout-2026-10",
    variationId: "compact",
  },
];

// Call when the configured exposure condition is reached.
trackExperimentExposure(
  { experiments, trigger: "scroll_50_percent" },
  ["psykhe-ai"],
);

trigger is an optional string of up to 128 characters that describes the condition. Omit it and call trackExperimentExposure({ experiments }, ["psykhe-ai"]) when you do not need a description. At least one experiment is required. Every entry must have nonblank experiment and variation identifiers. The helper rejects incomplete identifiers and invalid optional fields before tracking. Exposures without a complete experiment context are rejected by PSYKHE AI.

An exposure reports that the chosen condition occurred. It does not automatically prove that a recommendation rendered or became visible. Keep the condition consistent between variants and use your usual interaction events to report views and clicks.

Experiment fields

FieldRequiredType and limitMeaning
experimentIdYesNonblank string, up to 160 charactersStable experiment identifier or tracking key. Use a new identifier for a distinct test run.
variationIdYesNonblank string, up to 100 charactersThe variant the shopper receives, including baseline. Supports any number of variants.
hashAttributeNoString or null, up to 100 charactersName of the attribute used to assign the variant, such as customerId.
hashValueNoString or null, up to 160 charactersOriginal value of that assignment attribute, such as customer-123.
customNoArray or nullOptional key/value entries with string key and string or null value for additional experiment data.

Keep identifiers consistent across exposure and interaction events. Send only additional data you need in custom; omit unavailable optional fields. Experiment and variant names are not required.

Optional assignment inputs

Send hashAttribute and hashValue when your experimentation logic makes its assignment inputs available. For example, if it assigns variants by hashing a customer identifier:

trackExperimentExposure(
  {
    experiments: [
      {
        experimentId: "recommendations-2026-10",
        variationId: "baseline",
        hashAttribute: "customerId",
        hashValue: "customer-123",
      },
    ],
    trigger: "scroll_50_percent",
  },
  ["psykhe-ai"],
);

hashValue contains the value that was hashed. Use the original assignment input; you do not need to calculate another hash for tracking. These details can help explain assignments when the test uses a customer, account, or device identifier that differs from the tracker's browser identity. PSYKHE AI records the supplied values with the experiment; your experimentation logic chooses the variant.

Both fields are optional. If the inputs are unavailable or unnecessary for your analysis, omit them or use null. An exposure requires only experimentId and variationId in each experiment entry. The tracker supplies its normal identity fields independently.

Every integration uses the same contract, regardless of which system chooses the variant. The plugin validates supplied values against the types and limits above without inferring assignment inputs or checking how the variant was chosen. Do not substitute the tracker's browser identifier unless you know the experiment used it for assignment. These optional fields do not change tracker identity or control traffic allocation.

Attach contexts to later interactions

When decisions are available, pass the same experiments array on list views, list clicks, cart actions, transactions, and other ecommerce helpers. This option is optional on ordinary interactions and works alongside recommendation contexts:

import {
  trackProductListView,
  withRecommendIdCtx,
} from "@psykhe-ai/browser-plugin-snowplow-ecommerce";

trackProductListView(
  {
    name: "recommendations",
    products: [{ product_id: "sku-123", price: 100, currency: "usd" }],
    context: [withRecommendIdCtx("recommendation-id")],
    experiments,
  },
  ["psykhe-ai"],
);

For standard Snowplow functions, use withExperimentCtx to build contexts:

import { trackPageView } from "@snowplow/browser-tracker";
import { withExperimentCtx } from "@psykhe-ai/browser-plugin-snowplow-ecommerce";

trackPageView({ context: experiments.map(withExperimentCtx) }, ["psykhe-ai"]);

Attaching experiments describes that interaction; it does not create another exposure. Your integration supplies the currently applicable experiments on each page. The plugin does not remember them automatically. Stop attaching experiments when they no longer apply. If a later event cannot carry them, still send the separate exposure event using the same tracker and browser identity.

On this page