Collection of functions responsible for tracking user activity in an Eitri-App using CleverTap SDK.

CleverTap is a CRM and engagement platform that provides event tracking, push notifications, and user identification capabilities.

Requirements: This feature must be enabled in the Eitri Shopping App native configuration by providing the cleverTap configuration (account id and token) in the app configuration file.

Methods

  • Variables (Product Config / Feature Flags): declares a variable and its default value.

    A "Variable" is a server-driven setting your app reads at runtime — a feature flag (true/false) or a typed config value (number or string) that can differ per user/segment. It lets you change behavior without an app-store release (e.g. a free-shipping threshold, a payment-option toggle, an A/B-test layout choice).

    Only scalar types are supported: boolean, number, and string. The underlying CleverTap SDK maps number to one of its numeric kinds (int/long/float/double); JavaScript has a single number type, so if numeric precision matters (e.g. currency), prefer explicit handling in your app rather than relying on the numeric kind chosen by the default's shape. Objects and arrays are NOT supported — the SDK has no dictionary/map variable type reachable through this bridge, so passing one rejects with eitri.clevertap.defineVariable.error.unsupportedType instead of registering a variable that could never sync with the server. To carry structured data, define individual scalar variables (one per field) or encode it yourself into a string.

    Define-before-fetch: the CleverTap SDK only returns server values for variables that were declared first. So the usage order is always: defineVariable (for each variable you care about, with a safe default) → fetchVariablesgetVariable. The default you pass here is the value returned until the first successful fetchVariables binds the server value; it also selects the variable's type. Late/dynamic definition behavior is SDK-version-dependent.

    Example:

    const modules = await Eitri.modules();
    const defineVariable = modules?.cleverTap?.defineVariable;
    if (!defineVariable) return;

    await defineVariable({ name: "free_shipping_threshold", defaultValue: 199.90 });
    await defineVariable({ name: "enable_pix_installments", defaultValue: false });
    await modules.cleverTap.fetchVariables();
    const threshold = await modules.cleverTap.getVariable({ name: "free_shipping_threshold" });

    Parameters

    • param: { defaultValue: string | number | boolean; name: string }

      Object describing the variable.

      • defaultValue: string | number | boolean

        Default value and type selector. Must be a scalar: boolean, number, or string. Objects/arrays are not supported and reject with eitri.clevertap.defineVariable.error.unsupportedType (see above).

      • name: string

        The variable name (must match the name configured in the CleverTap dashboard).

    Returns Promise<CleverTapVariableResult>

    The variable's current value (the default until a successful fetch binds the server value).

  • Variables: fetches the latest values of all defined variables from the CleverTap server.

    Call this after declaring your variables with defineVariable and before reading them with getVariable. Resolves once the SDK has responded.

    Example:

    const modules = await Eitri.modules();
    const fetchVariables = modules?.cleverTap?.fetchVariables;
    if (!fetchVariables) return;

    const result = await fetchVariables();
    if (result.success) {
    // variables are now populated with server values
    }

    Returns Promise<CleverTapFetchResult>

    { success }true when the server sync succeeded.

  • Native Display: returns a single display unit by its id, or undefined if none matches.

    Example:

    const modules = await Eitri.modules();
    const getDisplayUnitById = modules?.cleverTap?.getDisplayUnitById;
    if (!getDisplayUnitById) return;

    const unit = await getDisplayUnitById({ unitId: "1234567890" });
    if (unit) {
    // render it with your own components
    }

    Parameters

    • param: { unitId: string }

      Object identifying the display unit.

      • unitId: string

        The unitId of a display unit previously obtained from getDisplayUnits.

    Returns Promise<undefined | CleverTapDisplayUnit>

    The matching display unit, or undefined.

  • Native Display (CMS-like read API): returns all display units currently targeted to the user.

    Native Display is a server-driven content channel: a marketer configures content blocks (banners, carousels, custom key-value payloads) and their targeting in the CleverTap dashboard, and this method returns the ones that apply to the current user as data. The Eitri-App renders them with its own components — CleverTap draws no UI.

    Returns an empty array when CleverTap is disabled, has not yet synced, or no campaign targets the user. Because content can arrive after app start (the SDK syncs in the background), an Eitri-App should query on screen mount and re-query when notified — see the cleverTapDisplayUnitsUpdated event on Eitri.eventBus.

    Example:

    const modules = await Eitri.modules();
    const getDisplayUnits = modules?.cleverTap?.getDisplayUnits;
    if (!getDisplayUnits) return;

    const units = await getDisplayUnits();
    for (const unit of units) {
    // Render `unit.contents` / `unit.customExtras` with your own components,
    // then record the impression:
    await modules.cleverTap.recordDisplayUnitViewed({ unitId: unit.unitId });
    }

    Returns Promise<CleverTapDisplayUnit[]>

    The display units targeted to the current user, or an empty array.

  • Variables: reads the current value of a single variable by name.

    Returns value: null when the variable has never been defined (via defineVariable) or when CleverTap is disabled. Until the first successful fetchVariables, the value is the default supplied to defineVariable.

    Example:

    const modules = await Eitri.modules();
    const getVariable = modules?.cleverTap?.getVariable;
    if (!getVariable) return;

    const { value } = await getVariable({ name: "home_layout" });
    const layout = typeof value === "string" ? value : "grid";

    Parameters

    • param: { name: string }

      Object identifying the variable.

      • name: string

        The variable name previously passed to defineVariable.

    Returns Promise<CleverTapVariableResult>

    The variable's current { name, value }.

  • Logs a purchase (Charged) event with CleverTap SDK.

    CleverTap models purchases with a dedicated Charged event composed of the overall charge details plus a list of the purchased items. Provide the charge-level details as top-level keys, and the purchased products as an array under the items key. The items array is split out and sent to CleverTap's native recordChargedEvent / pushChargedEvent separately from the charge details.

    The charge-detail keys and each item's keys are passed to CleverTap verbatim, so they should follow CleverTap's Charged-event conventions (e.g. the transaction total belongs in a property called "Amount"). See the official reference for the reserved properties: https://developer.clevertap.com/docs/events

    Note: the top-level items key is reserved by this bridge (it is what gets routed to the native charged-event API) and must be lowercase — it is independent of CleverTap's own keys.

    Supported value types for the charge details and for each item are: string, number, and boolean.

    Example:

    const modules = await Eitri.modules();
    const logChargedEvent = modules?.cleverTap?.logChargedEvent;
    if (!logChargedEvent) return;

    await logChargedEvent({
    "Amount": 129.97,
    "Payment Mode": "Credit Card",
    "Charged ID": "order-001",
    items: [
    { "Product Name": "T-Shirt", "Category": "Apparel", "Price": 29.99, "Quantity": 1 },
    { "Product Name": "Sneakers", "Category": "Footwear", "Price": 99.98, "Quantity": 1 }
    ]
    })

    Parameters

    • charge: Record<string, any> & { items?: Record<string, string | number | boolean>[] }

      Object describing the purchase. Top-level keys are the charge details; the optional items array contains the purchased products. Values must be primitives (string, number, or boolean).

    Returns Promise<undefined>

  • Logs an event with CleverTap SDK, where each parameter of the event is defined as a key-value pair within the data object.

    Supported value types for the data object are: string, number, and boolean.

    The eventName and the keys of data are passed to CleverTap verbatim, so they should follow CleverTap's own event and property naming conventions (Title Case, e.g. "Product Name"). See the official CleverTap events reference for naming guidance and reserved properties: https://developer.clevertap.com/docs/events

    Example:

    const modules = await Eitri.modules();
    const logEvent = modules?.cleverTap?.logEvent;
    if (!logEvent) return;

    await logEvent({
    eventName: "Product viewed",
    data: {
    "Product Name": "Casio Chronograph Watch",
    "Category": "Mens Accessories",
    "Price": 59.99
    }
    })

    Parameters

    • param: { data: Record<string, string | number | boolean>; eventName: string }

      Object describing the event.

      • data: Record<string, string | number | boolean>

        Object describing the event's data. Values must be primitives (string, number, or boolean).

      • eventName: string

        Name of the event.

    Returns Promise<undefined>

  • Native Display: records a click for a display unit.

    Call this when the user taps the rendered unit (or its call-to-action) so CleverTap's campaign analytics reflect the click.

    Example:

    const modules = await Eitri.modules();
    const recordDisplayUnitClicked = modules?.cleverTap?.recordDisplayUnitClicked;
    if (!recordDisplayUnitClicked) return;

    await recordDisplayUnitClicked({ unitId: unit.unitId });

    Parameters

    • param: { unitId: string }

      Object identifying the display unit.

      • unitId: string

        The unitId of the clicked display unit.

    Returns Promise<undefined>

  • Native Display: records an impression (viewed) for a display unit.

    Call this once you have actually rendered the unit on screen so CleverTap's campaign analytics reflect the impression.

    Example:

    const modules = await Eitri.modules();
    const recordDisplayUnitViewed = modules?.cleverTap?.recordDisplayUnitViewed;
    if (!recordDisplayUnitViewed) return;

    await recordDisplayUnitViewed({ unitId: unit.unitId });

    Parameters

    • param: { unitId: string }

      Object identifying the display unit.

      • unitId: string

        The unitId of the rendered display unit.

    Returns Promise<undefined>

  • Records a screen view with CleverTap SDK and sets the session's current-screen context.

    Calling this has two effects:

    1. Screen context for all subsequent eventsscreenName becomes the session's current screen, and the SDK attaches it to every event sent afterwards (logEvent, logChargedEvent, profile updates) until the next recordScreen call. Because an Eitri Shopping App runs inside a single native container screen, without this call every event carries the same container screen name regardless of where the user actually was.
    2. A page-visit record — feeds CleverTap's session analytics (screens visited per session), visible in the user profile's activity data.

    This does NOT produce a named event. Screen views recorded here never appear in the dashboard's Events section or in the Event Debugger, cannot trigger campaigns, and cannot be used to build segments. If you need a segmentable, campaign-triggerable screen view, send a regular event instead (or in addition), e.g. logEvent({ eventName: "Screen Viewed", data: { "Screen Name": "Product Detail" } }).

    Call this whenever a screen becomes visible to the user (e.g. on every route change). Consecutive calls with the same screenName may be deduplicated by the SDK — the screen is already "current" — so do not rely on repeat calls producing additional records.

    The screenName is passed to CleverTap verbatim; prefer stable, human-readable names (e.g. "Home", "Product Detail", "Cart") over internal route paths.

    If screenName is missing, empty, or not a string, an error is thrown.

    Warning

    Not tab-scoped — races when multiple Eitri Machines run concurrently. The "current screen" this call sets is process-wide CleverTap SDK state, shared by every Eitri Machine instance in the app, not scoped to the calling machine or tab. When a bottom tab bar keeps several Eitri Machines alive at once, a background tab's recordScreen call can overwrite the screen context set by the tab the user is actually looking at — whichever call reaches the SDK last wins, regardless of which tab is visible. Avoid calling recordScreen from an Eitri-App instance that may run as a non-foreground tab unless you can guarantee it is the currently visible one.

    Example:

    const modules = await Eitri.modules();
    const recordScreen = modules?.cleverTap?.recordScreen;
    if (!recordScreen) return;

    await recordScreen({ screenName: "Product Detail" });

    Parameters

    • param: { screenName: string }

      Object describing the screen view.

      • screenName: string

        Name of the screen being viewed, passed to CleverTap verbatim.

    Returns Promise<undefined>

  • Sets user consent preferences for CleverTap.

    Only the fields provided in the parameter object will be updated. Omitted fields will NOT be modified, allowing partial updates.

    Example:

    const modules = await Eitri.modules();
    const setUserOptins = modules?.cleverTap?.setUserOptins;
    if (!setUserOptins) return;

    // Opt the user back in
    await setUserOptins({ tracking: true })

    // Or opt-out entirely (GDPR/LGPD)
    await setUserOptins({ tracking: false })

    Parameters

    • optins: CleverTapUserOptins

      Object containing consent preferences. Only provided fields will be updated.

    Returns Promise<undefined>

  • Starts CleverTap geofence tracking for location-based campaigns.

    Requires the CleverTap geofence feature to be enabled in the native configuration (cleverTap.geofence.active) AND location permissions to be granted by the user.

    You must call it once per app launch, ideally on app start and after permission handling.

    Users must allow "Always" and "Precise Location" permissions for geofencing to work correctly. The geofences themselves are configured in the CleverTap dashboard; this call activates monitoring on the device.

    Example:

    // Ensure that the methods exist
    const modules = await Eitri.modules();
    const upgradeToBackgroundPermission = modules?.geolocation?.upgradeToBackgroundPermission;
    const startGeofenceTracking = modules?.cleverTap?.startGeofenceTracking;

    if (!upgradeToBackgroundPermission) {
    console.log("upgradeToBackgroundPermission is not available");
    return;
    }

    if (!startGeofenceTracking) {
    console.log("startGeofenceTracking is not available");
    return;
    }

    // Check and request location permissions

    // First ensure foreground permission
    const foreground = await modules.geolocation.requestPermission({ precision: "precise" });
    if (foreground.status != "GRANTED") {
    console.log("Location permission not granted");
    return;
    }

    // Explain to the user why background permission is needed, then request it

    // Try upgrade to background
    const background = await upgradeToBackgroundPermission();

    // Then start geofence tracking
    await startGeofenceTracking();

    Returns Promise<undefined>