Skip to main content
Commerce Engine analytics has two independent layers:
  1. @commercengine/analytics — a vendor-neutral, zero-runtime-dependency mapping package that turns canonical Commerce Engine entities into Segment/RudderStack-compatible ecommerce envelopes.
  2. Hosted Checkout analytics forwarding — Hosted Checkout uses that package internally and sends the resulting envelopes to the parent application through onAnalyticsEvent.
The mapper package is not tied to Hosted Checkout, the Storefront SDK, Segment, or RudderStack. It can be used with:
  • Hosted Checkout
  • a custom checkout built with @commercengine/storefront
  • a custom checkout calling the REST API directly
  • browser analytics SDKs
  • server-side CDP SDKs
  • raw HTTP ingestion
  • a fully custom analytics implementation

Mental model

@commercengine/analytics performs only the mapping step. It does not:
  • load a vendor SDK
  • send network requests
  • manage consent
  • store identity
  • persist an event queue
  • prescribe where events must be delivered
That separation keeps event schemas consistent while leaving transport, consent, batching, retries, and destination ownership to the application.

Install the mapper package

It consumes canonical Commerce Engine types through a type-only peer dependency:
  • Applications using @commercengine/storefront already satisfy that dependency.
  • REST-only TypeScript applications should also install the generated SDK type package:
The analytics bundle itself has no runtime dependency on either SDK package; the peer exists so mapper inputs remain type-safe.

Three supported integration modes

Hosted Checkout

Hosted Checkout maps cart, coupon, checkout-step, payment, identity, and order interactions internally. The parent receives completed envelopes and only needs to forward them.
Use @commercengine/checkout version 0.5.0 or later for onAnalyticsEvent. This minimal adapter forwards track events only; identity handling depends on which layer owns the Commerce Engine session and is covered below.
Do not rebuild the same checkout events in the parent application. Hosted Checkout already maps them from the canonical cart and order entities. Re-emitting them from both layers creates duplicate conversions and schema drift.

Custom checkout with the Storefront SDK

A custom checkout owns the customer interaction, so it decides when an event has occurred. Map the canonical entity returned by the SDK at that point.
For a payment-required order, do not emit Order Completed after createOrder() or after one immediate status check. Provider callbacks are asynchronous, so the first response will commonly remain pending. Run conversion tracking from the same payment-return flow that drives the customer-facing result, or from a server-side payment-success webhook. A browser return flow should wait through pending states with a bounded verifier:
Do not start a second polling loop solely for analytics. Reuse the authoritative payment-status flow that already drives the checkout return page. If the bounded check ends in pending or times out, do not emit the conversion; let a later payment-return visit, account refresh, or idempotent server webhook record completion once success is authoritative. The package maps the entity; your application still owns the semantic trigger. For example, emit Checkout Started when the customer actually begins checkout, not merely because a cart happened to load.

Custom checkout with direct REST calls

The package works the same way when the Commerce Engine entity came from REST rather than the TypeScript SDK.
For payment-required REST orders, use the same bounded pending-state loop in the payment-return flow—or an idempotent server webhook—until GET /orders/{order_number}/payment-status reports success. Then retrieve GET /orders/{order_number} and map that current Order with toOrderCompleted(). One immediate status check and a redirect back from the payment provider are not proof of payment success. Prefer generated Commerce Engine types even in REST integrations. Do not create parallel hand-written cart, product, and order interfaces that can drift from the API.

Entity mappers

The package includes pure mappers for events that can be derived from canonical Commerce Engine entities. The mappers derive currency and standard monetary fields from the entity. Product mappers also normalize differences between Product, ProductDetail, and flattened Item shapes.

Selected variants

A parent product can represent several variants. Pass the selected variant when mapping a product interaction:
The selected variant overrides the emitted SKU, price, image, variant name, variant ID, and variant slug. Without an explicit selection, the mapper uses the default variant when one exists.

Product list events

Avoid rebuilding product arrays manually or hardcoding currency. Let the mapper normalize the Commerce Engine entities.

Events without a single source entity

Use trackEvent for actions such as coupons, promotions, wishlist interactions, reviews, and custom business events.
For custom events, reuse the package’s property builders instead of reconstructing canonical cart or order fields.

Browser, server, and HTTP delivery

The mapper returns a complete Segment/RudderStack HTTP-style envelope. Adapt it to the delivery API you use.

Browser SDK

Browser SDKs typically keep identity in ambient state and expect (event, properties):
Do not pass the whole envelope to a Segment-style browser track() method. analytics.track(eventEnvelope) is interpreted as an event-name argument. Use trackArgs or pass event.event and event.properties separately.

Server SDK

A server process has no ambient browser identity. Add identity to the mapper context and pass the resulting envelope fields to the server SDK.

Raw HTTP

A compatible ingestion endpoint can accept the complete envelope unchanged:

Identity ownership

Identity is separate from event mapping. Choose one owner for each application architecture.

Storefront SDK + Hosted Checkout

When using authMode: "provided", the parent Storefront SDK owns tokens and identity. A sound pattern is:
  • Hosted Checkout forwards track envelopes
  • Storefront SDK token updates drive identify
  • Hosted Checkout identify envelopes are ignored to avoid a second identity path

Checkout-only integration

When Hosted Checkout uses authMode: "managed", it owns the session. The parent adapter can consume both track and identify envelopes. Handle anonymous identity using the destination’s supported anonymous-ID API. Do not call identify(undefined, traits).

Custom checkout

A custom checkout can use toIdentify, identifyArgs, or userTraits with either a full Commerce Engine User or the JWT-derived UserInfo.
The mapper distinguishes a true anonymous user from a known user. It does not equate “logged out” with “anonymous”; a logged-out user can still be a known Commerce Engine identity.

Hosted Checkout events

Hosted Checkout currently uses the mapper package internally for customer actions including: Checkout-step events can include a numeric step, a more specific step_name, the selected shipping method, and the selected payment method. Hosted Checkout suppresses duplicate emission for key session-level signals such as checkout start, recommendation views, and order completion. Downstream destinations should still apply their normal idempotency and deduplication policies.

Data minimization

The standard property builders intentionally avoid copying large operational objects into analytics payloads. Raw addresses, shipments, inventory lots, seller details, payment authentication data, tokens, and OTP values are not included by default. Add custom properties only when they serve a defined analytics purpose and comply with the application’s consent and privacy policy.

Common mistakes

Verification checklist

@commercengine/analytics

Browse the current package documentation, exported mappers, types, and source.