@chordcommerce/analytics
Version:
Chord Commerce event tracking
200 lines (199 loc) • 9.14 kB
TypeScript
import type { AnyAnalytics, EventProperties, Options, ValidateResult, ChordAnalyticsOptions, AnyOptions, CartViewedInput, IdentifyTraits, CheckoutStartedInput, CheckoutStepCompletedInput, CheckoutStepViewedInput, EmailCapturedInput, ProductListViewedInput, ProductListFilteredInput, ProductAddedInput, ProductClickedInput, VariantClickedInput, ProductRemovedInput, ProductViewedInput, ProductsSearchedInput, CouponAppliedInput, CouponDeniedInput, CouponEnteredInput, CouponRemovedInput, SignedInInput, SignedOutInput, SignedUpInput, LoginStartedInput, ObjectTypes, OrderCompletedInput, SubscriptionCancelledInput, NavigationClickedInput, PaymentInfoEnteredInput } from '../types/index.js';
import { AnalyticsMiddleware } from '../types/client.js';
export interface ChordAnalyticsSnippet {
_loadOptions: ChordAnalyticsOptions<ObjectTypes>;
invoked: boolean;
methods: string[];
queue: any[];
factory: (method: string) => () => ChordAnalytics;
load: () => void;
SNIPPET_VERSION: string;
}
export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
/**
* Allows snippet.js to detect whether this library has been initialized yet.
*/
initialize: true;
/**
* Allows snippet.js to detect whether the snippet has started running yet.
*/
invoked: true;
/**
* Options for ChordAnalytics.
*/
options: ChordAnalyticsOptions<T>;
/**
* Middleware to be applied to the event properties
*/
middleware: any[];
/**
* Promise that resolves when CDP is ready
*/
private cdpReadyPromise;
private consentConfig;
private resetCompletePromise;
/**
* Queue for events waiting for consent to be ready
*/
private consentEventQueue;
/**
* Whether we're currently waiting for consent and watching for it
*/
private consentWatcherActive;
/**
* Promise that resolves when consent is ready (shared across all queued events)
*/
private consentReadyPromise;
constructor(options: ChordAnalyticsOptions<T>);
/**
* Persist the consent event queue to sessionStorage for recovery on instance recreation.
* Validates queue size before storing to prevent QuotaExceededError.
*/
private persistQueueToStorage;
/**
* Restore pending events from sessionStorage (keeps events less than 5 min old).
* Called on new instance initialization.
*/
private restoreQueueFromStorage;
/**
* Clear the persisted queue from sessionStorage after successful flush.
*/
private clearQueueFromStorage;
/**
* Initialize CDP snippet and wait for it to be ready.
* Fires initial consent track event after CDP is fully initialized to avoid circular await.
*/
private initializeCdp;
/**
* Set debug mode for Chord Analytics
* @param enabled - Whether debug mode should be enabled
*/
setDebugMode: (enabled: boolean) => void;
cdp: () => AnyAnalytics;
ccdp: () => AnyAnalytics;
logger: (message?: any, ...optionalParams: any[]) => void;
isResetting: () => boolean;
private waitForReadyState;
/**
* Wait for consent manager to be ready (no timeout - queues indefinitely).
* Uses a shared promise so multiple events share the same watcher.
*/
private waitForConsent;
/**
* Queue an event to be sent when consent is ready.
* Persists to sessionStorage for recovery on instance recreation.
* Starts a consent watcher if not already active.
*/
private queueEventForConsent;
/**
* Watch for consent to become ready, then flush the queue.
*/
private watchForConsentAndFlush;
/**
* Flush all queued events now that consent is ready.
* Clears sessionStorage after successful flush.
*/
private flushConsentQueue;
/**
* Configure CDP with fresh consent categories before each event.
* Uses Jitsu's configure() to update privacy.consentCategories.
*/
private configureConsentOnCdp;
validate: (event: string, props: EventProperties) => ValidateResult[];
/**
* Generate the event `meta` property.
*/
meta: () => {
ownership: {
oms_id: string;
store_id: string;
tenant_id: string;
};
version: {
major: number;
minor: number;
patch: number;
};
i18n: import("../types/client.js").i18nMetadata;
platform: import("../types/client.js").platformMetadata;
store: import("../types/client.js").storeMetadata;
};
addSourceMiddleware: (func: AnalyticsMiddleware) => void;
/**
* Send a `track` event to the CDP with any event name and properties.
* If consent is not ready, the event is queued until consent is available.
*/
track: (event: string, props?: EventProperties, options?: Options) => Promise<void>;
/**
* Internal method to actually send a track event to CDP.
*/
private sendTrackEvent;
/**
* Send an `identify` event to the CDP with user id and traits.
* If consent is not ready, the event is queued until consent is available.
*/
identify: {
(userId?: string, traits?: IdentifyTraits, options?: AnyOptions): Promise<void>;
(traits?: IdentifyTraits, options?: AnyOptions): Promise<void>;
};
/**
* Internal method to actually send an identify event to CDP.
*/
private sendIdentifyEvent;
/**
* Send a `page` event to the CDP.
* If consent is not ready, the event is queued until consent is available.
*/
page: {
(props?: Record<string, any>, options?: Options): void;
};
/**
* Internal method to actually send a page event to CDP.
*/
private sendPageEvent;
reset: () => Promise<void>;
private performReset;
/**
* Handler for postMessage events from the Shopify Web Pixel sandbox.
* Bound to the instance for proper `this` context and cleanup.
*/
private webPixelMessageHandler;
/**
* Set up a listener for postMessage events from the Shopify Web Pixel sandbox.
* This allows the web pixel (running in Shopify's sandboxed iframe)
* to forward analytics events to this ChordAnalytics instance on the storefront.
*
* The web pixel sends messages in the format:
* - { source: 'chord-web-pixel', type: 'track', payload: [eventName, properties] }
* - { source: 'chord-web-pixel', type: 'identify', payload: [userId, traits] }
* - { source: 'chord-web-pixel', type: 'page', payload: [properties] }
*
* @returns A cleanup function to remove the listener
*/
setupWebPixelListener: () => (() => void);
trackCartViewed: (props: CartViewedInput<T>, options?: AnyOptions) => Promise<void>;
trackCheckoutStarted: (props: CheckoutStartedInput<T>, options?: AnyOptions) => Promise<void>;
trackCheckoutStepCompleted: (props: CheckoutStepCompletedInput, options?: AnyOptions) => Promise<void>;
trackCheckoutStepViewed: (props: CheckoutStepViewedInput, options?: AnyOptions) => Promise<void>;
trackCouponApplied: (props: CouponAppliedInput, options?: AnyOptions) => Promise<void>;
trackCouponDenied: (props: CouponDeniedInput, options?: AnyOptions) => Promise<void>;
trackCouponEntered: (props: CouponEnteredInput, options?: AnyOptions) => Promise<void>;
trackCouponRemoved: (props: CouponRemovedInput, options?: AnyOptions) => Promise<void>;
trackEmailCaptured: (props: EmailCapturedInput, options?: AnyOptions) => Promise<void>;
trackProductAdded: (props: ProductAddedInput<T>, options?: AnyOptions) => Promise<void>;
trackProductClicked: (props: ProductClickedInput<T>, options?: AnyOptions) => Promise<void>;
trackVariantClicked: (props: VariantClickedInput<T>, options?: AnyOptions) => Promise<void>;
trackProductListFiltered: (props: ProductListFilteredInput, options?: AnyOptions) => Promise<void>;
trackProductListViewed: (props: ProductListViewedInput<T>, options?: AnyOptions) => Promise<void>;
trackProductRemoved: (props: ProductRemovedInput<T>, options?: AnyOptions) => Promise<void>;
trackProductViewed: (props: ProductViewedInput<T>, options?: AnyOptions) => Promise<void>;
trackProductsSearched: (props: ProductsSearchedInput, options?: AnyOptions) => Promise<void>;
trackSignedIn: (props: SignedInInput, options?: AnyOptions) => Promise<void>;
trackSignedOut: (props?: SignedOutInput, options?: AnyOptions) => Promise<void>;
trackSignedUp: (props?: SignedUpInput, options?: AnyOptions) => Promise<void>;
trackLoginStarted: (props: LoginStartedInput, options?: AnyOptions) => Promise<void>;
trackSubscriptionCancelled: (props: SubscriptionCancelledInput, options?: AnyOptions) => Promise<void>;
trackNavigationClicked: (props: NavigationClickedInput, options?: AnyOptions) => Promise<void>;
trackPaymentInfoEntered: (props: PaymentInfoEnteredInput, options?: AnyOptions) => Promise<void>;
trackOrderCompleted: (props: OrderCompletedInput, options?: AnyOptions) => Promise<void>;
}