Clickstream Webhook

Overview

Tapcart's clickstream webhook delivers realtime behavioral events from your mobile app to an endpoint you configure. Each event represents a discrete shopper action, such as opening the app, viewing a product, adding to cart, initiating checkout, and more. This document describes the full structure and meaning of every supported event type, and how to configure a webhook to begin receiving events.

Events are delivered as HTTP POST requests to your configured endpoint. The request body is a JSON object containing the event type, event specific data, and device / session context.


Configuration

In your Tapcart dashboard under settings, there is a Webhooks section where you can globally enable or disable the feature, as well as enter your https endpoint. Below is the list of clickstream events which are eligible to be consumed via webhook. You can select all, or a subset of these to be delivered to your endpoint, allowing you to control the desired data volume entering your system.

Event TypeDescription
applicationInstalledApp installed for the first time
applicationOpenedApp opened / brought to foreground
cartAddItem added to the Shopify cart
cartRemoveItem removed from the Shopify cart
cartUpdatedCart state changed (quantity update, discount applied, etc.)
checkoutCreatedShopper tapped the checkout button
collectionViewedShopper opened a product collection
loggedInShopper logged in
loggedOutShopper logged out
pageViewShopper viewed a screen
searchShopper submitted a search query
productViewedShopper opened a product detail page
purchaseCompletedShopper completed a purchase / placed an order
pushOpenedShopper opened a push notification
wishlistItemAddedShopper added an item to a Tapcart wishlist

Request Structure

Every webhook payload shares the same top level structure, regardless of event type.

{
  "event": "cartAdd",
  "data": { ... },
  "properties": { ... },
  "mp_metadata": {
    "mp_event_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "mp_session_id": "ffffffff-0000-1111-2222-333333333333"
  }
}
FieldTypeDescription
eventstringThe event type name (see table above).
dataobjectEvent-specific payload. Structure varies by event type — documented in detail below.
propertiesobjectDevice and session context present on every event. See Common Properties below.
mp_metadataobjectAnalytics tracking identifiers. mp_event_id is a globally unique identifier for this event (use for deduplication); mp_session_id identifies the app session that produced it.

Requests also include headers to signal high level data about the nature of the request. This can be helpful if you require additional filtering prior to parsing the request body itself. Below are some of the available headers.

Headerexample
appidABC123
eventtypepageView
deviceid00000000-1111-2222-3333-444444444444
eventid00000000-1111-2222-3333-444444444444


Common Properties

The properties object carries device, locale, and session context on every event. Most fields are always present; a small number are conditional (noted below).

{
  "appId": "ABC123",
  "device_id": "00000000-1111-2222-3333-444444444444",
  "distinct_id": "device:55555555-6666-7777-8888-999999999999",
  "time": 1778873103209,
  "os": "android",
  "os_version": 30,
  "country": "GB",
  "language": "en",
  "timezone": "Europe/London",
  "trackingEnabled": true,
  "tapcart_build": "20.19.0",
  "lib_version": "5.2.0",
  "version_code": "174",
  "version_name": "174",
  "userGroup": "userGroup016",
  "userId": null,
  "tags": []
}

Identifiers

FieldTypeDescription
appIdstringYour Tapcart app identifier. Use this to confirm the event belongs to your store.
device_idstring (UUID)Stable identifier for the physical device. Persists across sessions and app updates.
distinct_idstringAnalytics identity for this user. Format is "device:<uuid>" for anonymous (not logged-in) shoppers and the Shopify Customer GID (e.g. "gid://shopify/Customer/5000000000001") after a successful login.
user_id / userIdstring | nullShopify Customer GID of the logged-in customer (e.g. "gid://shopify/Customer/5000000000001"). null when the shopper is not logged in. Both user_id and userId may appear; they carry the same value.
tagsstring[]Shopify customer tags assigned to the logged-in customer. Empty array for anonymous users.

Device & Platform

FieldTypeDescription
osstringOperating system: "android" or "ios".
os_versionstring | numberOS version. A number (Android API level, e.g. 30) on Android; a string (e.g. "18.1") on iOS.

Locale

Depending on individual device settings, some of these fields may or may not be populated reliably.

FieldTypeDescription
countrystring?ISO 3166-1 alpha-2 country code inferred from device settings (e.g. "US", "GB").
languagestring?BCP 47 language tag from device settings (e.g. "en", "ar").
timezonestring?IANA timezone string from device settings (e.g. "America/New_York").

App Context

FieldTypeDescription
timenumberUnix timestamp in milliseconds when the event occurred on-device.
tapcart_buildstringTapcart mobile app build version (e.g. "20.19.0").
lib_versionstringVersion of the Tapcart analytics SDK embedded in the app (e.g. "5.2.0").
version_codestringYour store's app build number as published to the app stores.
version_namestringYour store's app version name as published to the app stores.
trackingEnabledbooleanfalse if the shopper has opted out of analytics tracking (e.g. via the iOS App Tracking Transparency prompt). Events are still delivered when false; respect this flag in your data processing.
userGroupstringInternal A/B test cohort identifier (e.g. "userGroup014"). For internal Tapcart use.

Notes on Shopify Data in Event Payloads

Several event types include data enriched from the Shopify Storefront API. Keep the following in mind when processing these fields.

Global IDs (GIDs): Shopify resources use the format "gid://shopify/<ResourceType>/<numericId>" (e.g. "gid://shopify/Product/1000000000001"). The numeric portion can be extracted for use with the Shopify Admin API.

__typename: GraphQL objects from the Storefront API include a __typename field on every nested object (e.g. "__typename": "Cart"). This is a GraphQL introspection artifact and can be safely ignored.

MoneyV2: Monetary amounts are represented as objects with amount (a decimal string) and currencyCode (an ISO 4217 code):

{ "amount": "26.0", "currencyCode": "GBP" }

Relay pagination: Some nested Shopify collections use the Relay cursor pagination pattern ({ "edges": [{ "node": { ... } }] }) while others are plain arrays, depending on the API version and event type. Your parser should handle both shapes.


Event Types


applicationInstalled

Fired once when a shopper opens the app for the first time after installation. Use this to track new installs and attribute them to marketing campaigns.

Schema

{
  "event": "applicationInstalled",
  "data": { },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

This event carries no event specific data.


applicationOpened

Fired each time the app is brought to the foreground — on launch and on resume from background. Use this to measure daily/monthly active users and session starts.

Schema

{
  "event": "applicationOpened",
  "data": { },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

This event carries no event specific data.


cartAdd

Fired when a shopper adds a product variant to their Shopify cart. The data field contains a full snapshot of the cart at the time of the action, enriched with product and variant details from the Shopify Storefront API.

Schema

{
  "event": "cartAdd",
  "data": {
    "id": "gid://shopify/Cart/aaaaaaaaaaaaaaaaaaaaaaaa",
    "cartId": "gid://shopify/Cart/aaaaaaaaaaaaaaaaaaaaaaaa",
    "checkoutUrl": "https://www.example.com/cart/c/aaaaaaaaaaaaaaaaaaaaaaaa",
    "cost": {
      "subtotalAmount": { "amount": "26.0", "currencyCode": "GBP" },
      "totalAmount": { "amount": "26.0", "currencyCode": "GBP" }
    },
    "totalQuantity": 1,
    "updatedAt": "2026-04-24T19:26:03Z",
    "lineItems": [
      {
        "quantity": 1,
        "variantId": "gid://shopify/ProductVariant/20000000000001"
      }
    ],
    "lines": [
      {
        "id": "gid://shopify/CartLine/11111111-2222-3333-4444-555555555555?cart=aaaaaaaaaaaaaaaaaaaaaaaa",
        "quantity": 1,
        "cost": {
          "totalAmount": { "amount": "26.0", "currencyCode": "GBP" }
        },
        "discountAllocations": [],
        "attributes": [],
        "merchandise": {
          "id": "gid://shopify/ProductVariant/20000000000001",
          "title": "XL",
          "price": { "amount": "26.0", "currencyCode": "GBP" },
          "compareAtPrice": { "amount": "26.0", "currencyCode": "GBP" },
          "metafields": [],
          "product": {
            "id": "gid://shopify/Product/1000000000001",
            "title": "Example Product A",
            "handle": "example-product-a",
            "vendor": "Example Brand",
            "productType": "T-Shirts",
            "availableForSale": true,
            "requiresSellingPlan": false,
            "totalInventory": 4965,
            "tags": [],
            "metafields": [],
            "options": [
              {
                "id": "gid://shopify/ProductOption/30000000000001",
                "name": "Size",
                "values": ["S", "M", "L", "XL", "2XL"]
              }
            ],
            "priceRange": {
              "minVariantPrice": { "amount": "26.0", "currencyCode": "GBP" },
              "maxVariantPrice": { "amount": "26.0", "currencyCode": "GBP" }
            },
            "variants": {
              "edges": [
                {
                  "node": {
                    "id": "gid://shopify/ProductVariant/20000000000001",
                    "title": "XL",
                    "price": { "amount": "26.0", "currencyCode": "GBP" },
                    "compareAtPrice": { "amount": "26.0", "currencyCode": "GBP" },
                    "availableForSale": true,
                    "currentlyNotInStock": false,
                    "quantityAvailable": 993,
                    "requiresShipping": true,
                    "taxable": true,
                    "weight": 200,
                    "sku": "...",
                    "barcode": "...",
                    "selectedOptions": [{ "name": "Size", "value": "XL" }],
                    "image": {
                      "src": "https://cdn.shopify.com/...",
                      "url": "https://cdn.shopify.com/...",
                      "width": 2000
                    },
                    "metafields": []
                  }
                }
              ]
            },
            "variantsCount": { "count": 5 }
          }
        }
      }
    ],
    "buyerIdentity": {
      "countryCode": "GB",
      "deliveryAddressPreferences": []
    },
    "attributes": [],
    "discountCodes": [],
    "discountAllocations": [],
    "appliedGiftCards": [],
    "deliveryGroups": { "edges": [] },
    "note": ""
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

Key data Fields

FieldTypeDescription
id / cartIdstring (GID)Shopify Cart GID. Both fields carry the same value. Use either to correlate with Shopify's Storefront or Admin APIs.
checkoutUrlstring (URL)Direct URL to continue checkout in a browser. This is the URL Tapcart hands off to Shopify Checkout.
cost.subtotalAmountMoneyV2Cart subtotal before shipping and taxes.
cost.totalAmountMoneyV2Cart total (may equal subtotal before discounts and shipping are calculated).
totalQuantitynumberTotal number of items in the cart.
updatedAtstring (ISO 8601)When the cart was last modified on Shopify.
lineItemsarrayCompact client-side summary of items in the cart. Each entry has quantity and variantId (GID). Use lines for authoritative data.
linesarrayFull cart line items from the Shopify Storefront API.
lines[].idstring (GID)Unique CartLine GID. Encodes both the line UUID and the cart ID.
lines[].quantitynumberQuantity of this line item.
lines[].cost.totalAmountMoneyV2Total cost for this line (price × quantity, after line-level discounts).
lines[].discountAllocationsarrayDiscounts allocated to this specific line item.
lines[].attributesarrayCustom line item attributes (key/value pairs).
lines[].merchandiseobjectThe selected product variant (ProductVariant).
lines[].merchandise.idstring (GID)Shopify ProductVariant GID.
lines[].merchandise.titlestringVariant title (e.g. "XL").
lines[].merchandise.priceMoneyV2Selling price of this variant.
lines[].merchandise.compareAtPriceMoneyV2Original/compare-at price. Equal to price when there is no markdown.
lines[].merchandise.product.idstring (GID)Shopify Product GID.
lines[].merchandise.product.titlestringProduct title.
lines[].merchandise.product.handlestringShopify URL handle for the product.
lines[].merchandise.product.vendorstringProduct vendor.
lines[].merchandise.product.productTypestringProduct type as configured in Shopify.
lines[].merchandise.product.tagsstring[]Shopify product tags.
lines[].merchandise.product.totalInventorynumberTotal inventory across all variants.
lines[].merchandise.product.variants.edgesarrayAll product variants. Only the selected variant typically has full detail; others may be stub objects with only an id.
buyerIdentity.countryCodestringISO 3166-1 alpha-2 country code associated with the cart buyer.
discountCodesarrayDiscount codes applied to the cart. Each entry has applicable (boolean) and code (string).
appliedGiftCardsarrayGift cards applied to the cart.
attributesarrayCustom cart attributes (key/value pairs). May include Tapcart-specific entries such as { "key": "sales-channel", "value": "tapcart" }.
notestringOrder note attached to the cart.

cartRemove

Fired when a shopper removes a product from their cart. The data field reflects the cart state after removal. A convenience field data.lineItems identifies the removed item.

Schema

The top-level data structure is the same as cartAdd. The key difference is lineItems, which on cartRemove is a single object (not an array) describing the removed item:

{
  "event": "cartRemove",
  "data": {
    "id": "gid://shopify/Cart/bbbbbbbbbbbbbbbbbbbbbbbb",
    "cartId": "gid://shopify/Cart/bbbbbbbbbbbbbbbbbbbbbbbb",
    "checkoutUrl": "https://www.example.com/cart/c/bbbbbbbbbbbbbbbbbbbbbbbb",
    "cost": {
      "subtotalAmount": { "amount": "159.0", "currencyCode": "SGD" },
      "totalAmount": { "amount": "159.0", "currencyCode": "SGD" }
    },
    "totalQuantity": 1,
    "updatedAt": "...",
    "lineItems": {
      "currency": "SGD",
      "price": "239.0",
      "productId": "gid://shopify/Product/1000000000002",
      "productTitle": "Example Sneaker",
      "quantity": 1,
      "variantId": "gid://shopify/ProductVariant/20000000000002",
      "variantTitle": "4.5",
      "vendor": "Example Brand"
    },
    "lines": [ ... ],
    "buyerIdentity": { ... },
    "attributes": [],
    "discountCodes": [],
    "appliedGiftCards": [],
    "note": ""
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data.lineItems Fields

FieldTypeDescription
productIdstring (GID)Shopify Product GID of the removed item.
variantIdstring (GID)Shopify ProductVariant GID of the removed item.
productTitlestringProduct title of the removed item.
variantTitlestringVariant title of the removed item (e.g. "4.5").
pricestringPrice of the removed variant as a decimal string.
currencystringISO 4217 currency code.
quantitynumberQuantity of this line that was removed.
vendorstringProduct vendor.

Note: The lines field in cartRemove may use a Relay-style { "edges": [...] } pagination wrapper rather than a plain array, depending on the app version. Handle both shapes.


cartUpdated

Fired after any cart modification (quantity change, discount code applied, note updated, etc.) that does not specifically trigger cartAdd or cartRemove. Provides a lightweight cart snapshot useful for keeping external cart state in sync.

Schema

{
  "event": "cartUpdated",
  "data": {
    "id": "gid://shopify/Cart/aaaaaaaaaaaaaaaaaaaaaaaa",
    "cost": {
      "subtotalAmount": { "amount": "26.0", "currencyCode": "GBP" },
      "totalAmount": { "amount": "26.0", "currencyCode": "GBP" }
    },
    "totalQuantity": 1,
    "updatedAt": "2026-04-24T19:26:03Z",
    "discountCodes": [],
    "discountAllocations": [],
    "appliedGiftCards": [],
    "note": "",
    "lines": [
      {
        "id": "gid://shopify/CartLine/...",
        "quantity": 1,
        "cost": {
          "totalAmount": { "amount": "26.0", "currencyCode": "GBP" }
        },
        "discountAllocations": [],
        "attributes": [],
        "merchandise": {
          "id": "gid://shopify/ProductVariant/20000000000001",
          "title": "XL",
          "price": { "amount": "26.0", "currencyCode": "GBP" },
          "compareAtPrice": { "amount": "26.0", "currencyCode": "GBP" },
          "metafields": [],
          "product": { ... }
        }
      }
    ]
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

Key data Fields

FieldTypeDescription
idstring (GID)Shopify Cart GID.
costobjectCart subtotal and total amounts.
totalQuantitynumberTotal number of items currently in the cart.
updatedAtstring (ISO 8601)When the cart was last modified.
discountCodesarrayDiscount codes applied to the cart.
appliedGiftCardsarrayGift cards applied to the cart.
linesarrayCurrent cart line items. Same structure as in cartAdd.
notestringOrder note attached to the cart.

Note: Unlike cartAdd and cartRemove, this event does not include buyerIdentity, delivery, or deliveryGroups.


checkoutCreated

Fired when the shopper taps the checkout button, initiating the Shopify checkout flow. The data field wraps the full cart in a cart sub-object and adds a cartWasEmpty flag to distinguish standard checkouts from direct "Buy Now" flows.

Schema

{
  "event": "checkoutCreated",
  "data": {
    "cart": {
      "id": "gid://shopify/Cart/cccccccccccccccccccccccc",
      "checkoutUrl": "https://www.example.com/cart/c/cccccccccccccccccccccccc",
      "cartWasEmpty": true,
      "cost": {
        "subtotalAmount": { "amount": "6200.0", "currencyCode": "PHP" },
        "totalAmount": { "amount": "6200.0", "currencyCode": "PHP" }
      },
      "lines": [
        {
          "id": "gid://shopify/CartLine/...",
          "quantity": 1,
          "cost": {
            "totalAmount": { "amount": "6200.0", "currencyCode": "PHP" }
          },
          "discountAllocations": [],
          "attributes": [],
          "merchandise": {
            "id": "gid://shopify/ProductVariant/20000000000003",
            "compareAtPrice": { "amount": "6200.0", "currencyCode": "PHP" },
            "metafields": [],
            "product": {
              "id": "gid://shopify/Product/1000000000003",
              "title": "Example Athletic Shoe",
              "handle": "example-athletic-shoe",
              "availableForSale": true,
              "productType": "Shoes",
              "tags": ["example-tag-1", "example-tag-2"],
              "metafields": [
                { "key": "nickname", "value": "example-value" },
                { "key": "gender", "value": "WOMENS" }
              ],
              "options": [ ... ],
              "priceRange": { ... },
              "variants": [ ... ]
            }
          }
        }
      ],
      "buyerIdentity": { "countryCode": "PH", "deliveryAddressPreferences": [] },
      "attributes": [],
      "discountCodes": [],
      "discountAllocations": [],
      "appliedGiftCards": [],
      "deliveryGroups": []
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

Key data.cart Fields

The cart object mirrors the structure documented under cartAdd, with one notable addition:

FieldTypeDescription
cartWasEmptybooleantrue if the cart was empty when checkout was initiated, as happens with "Buy Now" / direct-to-checkout product flows. false for a standard cart checkout.

Note: In checkoutCreated, the cart lines array and nested variant/product objects do not use the __typename field seen in cartAdd and cartRemove. The data structures are otherwise equivalent.


collectionViewed

Fired when a shopper opens a product collection page within the app.

Schema

{
  "event": "collectionViewed",
  "data": {
    "collectionId": "100000000001",
    "collectionTitle": "100000000001"
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
collectionIdstringThe Shopify collection ID as a numeric string (not a GID). Use this to look up the collection via the Shopify Admin API.
collectionTitlestringThe display title of the collection. In some app configurations this field may be populated with the collection ID rather than the human-readable name.

loggedIn

Fired when a shopper successfully authenticates. After this event, subsequent events on this device will have properties.distinct_id set to the Shopify Customer GID.

Schema

{
  "event": "loggedIn",
  "data": {
    "userId": "gid://shopify/Customer/5000000000001",
    "tags": ["vip", "wholesale"]
  },
  "properties": {
    "userId": "gid://shopify/Customer/5000000000001",
    "tags": ["vip", "wholesale"],
    ...
  },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
userIdstring (GID)The Shopify Customer GID of the authenticated customer (e.g. "gid://shopify/Customer/5000000000001").
tagsstring[]Shopify customer tags assigned to this customer. Useful for segmentation (e.g. VIP status, wholesale accounts).

Note: userId and tags are also duplicated in properties on this event.


loggedOut

Fired when a shopper logs out. After this event, subsequent events on this device will have properties.distinct_id set back to the "device:<uuid>" format.

Schema

{
  "event": "loggedOut",
  "data": {
    "userId": null
  },
  "properties": {
    "userId": null,
    "tags": [],
    ...
  },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
userIdnullAlways null on logout — indicates no customer is currently authenticated.

pageView

Fired when a shopper views a screen in the app that does not have a more specific event type (i.e., screens other than product detail pages and collections). Use this to track general navigation patterns and session depth.

Schema

{
  "event": "pageView",
  "data": {
    "_analytics": {}
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
_analyticsobjectReserved for future analytics metadata. Currently always an empty object.


productViewed

Fired when a shopper opens a product detail page. The data field is a rich Shopify product object from the Storefront API, including all variants, images, metafields, and pricing information.

Schema

{
  "event": "productViewed",
  "data": {
    "id": "gid://shopify/Product/1000000000004",
    "productId": "1000000000004",
    "title": "Example Product B",
    "productTitle": "Example Product B",
    "handle": "example-product-b",
    "vendor": "Example Brand",
    "productType": "T Shirts",
    "availableForSale": true,
    "requiresSellingPlan": false,
    "publishedAt": "2026-03-27T17:00:02Z",
    "updatedAt": "2026-04-24T16:45:27Z",
    "productPrice": "26.0",
    "multiCurrencyCode": "GBP",
    "description": "...",
    "descriptionHtml": "<p>...</p>",
    "tags": [],
    "productTagsList": [],
    "metafields": [],
    "featuredImage": {
      "url": "https://cdn.shopify.com/...",
      "width": 2000,
      "height": 2000
    },
    "images": [
      {
        "url": "https://cdn.shopify.com/...",
        "altText": "Example Product B",
        "width": 2000,
        "height": 2000
      }
    ],
    "media": [
      {
        "mediaContentType": "IMAGE",
        "image": { "url": "https://cdn.shopify.com/..." }
      }
    ],
    "options": [
      {
        "id": "gid://shopify/ProductOption/30000000000002",
        "name": "Size",
        "values": ["S", "M", "L", "XL", "2XL"]
      }
    ],
    "priceRange": {
      "minVariantPrice": { "amount": "26.0", "currencyCode": "GBP" },
      "maxVariantPrice": { "amount": "26.0", "currencyCode": "GBP" }
    },
    "compareAtPriceRange": {
      "minVariantPrice": { "amount": "26.0", "currencyCode": "GBP" },
      "maxVariantPrice": { "amount": "26.0", "currencyCode": "GBP" }
    },
    "variants": [
      {
        "id": "gid://shopify/ProductVariant/20000000000004",
        "title": "S",
        "price": { "amount": "26.0", "currencyCode": "GBP" },
        "compareAtPrice": { "amount": "26.0", "currencyCode": "GBP" },
        "availableForSale": true,
        "selectedOptions": [{ "name": "Size", "value": "S" }],
        "image": {
          "id": "gid://shopify/ProductImage/40000000000001",
          "url": "https://cdn.shopify.com/...",
          "src": "https://cdn.shopify.com/...",
          "originalSrc": "https://cdn.shopify.com/...",
          "transformedSrc": "https://cdn.shopify.com/...",
          "width": 2000,
          "height": 2000
        }
      }
    ],
    "sellingPlanGroups": { "edges": [] },
    "seo": {
      "description": "..."
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

Key data Fields

FieldTypeDescription
idstring (GID)Shopify Product GID.
productIdstringNumeric Shopify Product ID extracted from the GID (without the gid://shopify/Product/ prefix).
title / productTitlestringProduct title. Both fields carry the same value.
handlestringShopify URL handle for the product (used in storefront URLs).
vendorstringProduct vendor.
productTypestringShopify product type as configured in the merchant's catalog.
availableForSalebooleantrue if any variant of this product is currently available for purchase.
requiresSellingPlanbooleantrue if the product can only be purchased through a subscription selling plan.
publishedAtstring (ISO 8601)When the product was published to the sales channel.
updatedAtstring (ISO 8601)When the product was last modified in Shopify.
productPricestringPrice of the first (default) variant as a decimal string.
multiCurrencyCodestringISO 4217 currency code in which the product is displayed to this shopper.
descriptionstringPlain-text product description (HTML stripped).
descriptionHtmlstringFull HTML product description as configured in Shopify.
tagsstring[]Shopify product tags.
productTagsListstring[]Alias for tags. May differ in some app configurations.
metafieldsarrayShopify product metafields configured for your app. Each entry has key and value strings.
featuredImageobjectThe product's primary image with url, width, and height.
imagesarrayAll product images. Each has url, altText, width, height.
mediaarrayAll product media (images, videos, 3D models). Each entry has mediaContentType ("IMAGE", "VIDEO", "MODEL_3D") and a type-specific image or sources payload.
optionsarrayProduct option definitions (e.g. Size, Color). Each has id, name, and values (all possible option values).
priceRangeobjectMin and max variant selling prices across the product.
compareAtPriceRangeobjectMin and max compare-at (original) prices across the product.
variantsarrayAll product variants as a flat array (not the edges/node Relay pattern used in cart events). Each variant includes id, title, price, compareAtPrice, availableForSale, selectedOptions, and image.
sellingPlanGroupsobjectAvailable subscription selling plans in Relay pagination format ({ "edges": [...] }). Empty when the product has no selling plans.
seo.descriptionstringSEO meta description for the product page.


purchaseCompleted

Fired when a shopper completes a purchase and an order is created. This is the conversion event — use it to attribute revenue and reconcile orders against earlier behavioral events. The data field carries the Shopify order identity, a snapshot of the purchased cart (line items and price breakdown), and the cart token.

The monetary amount values in this event are numbers (e.g. 110, 23.28), unlike the decimal-string amounts (e.g. "6200.0") found in the Storefront-API-sourced cart events such as cartAdd and checkoutCreated.

Schema

{
  "event": "purchaseCompleted",
  "data": {
    "id": "gid://shopify/OrderIdentity/5984563527820",
    "cart": {
      "token": "hWNDtrzjnmsS8VYuQZjXHIKy",
      "lines": [
        {
          "merchandiseId": "gid://shopify/ProductVariant/44257379352716",
          "productId": "gid://shopify/Product/8201169338508",
          "title": "T500",
          "quantity": 1,
          "price": { "amount": 110, "currencyCode": "MYR" },
          "image": {
            "altText": "...",
            "sm": "https://cdn.shopify.com/.../jd_CT500DA_a_64x64.jpg",
            "md": "https://cdn.shopify.com/.../jd_CT500DA_a_128x128.jpg",
            "lg": "https://cdn.shopify.com/.../jd_CT500DA_a_256x256.jpg"
          },
          "discounts": [
            {
              "title": "CHBJDZX8PV",
              "applicationType": "code",
              "value": 15,
              "valueType": "percentage",
              "amount": { "amount": 2.39, "currencyCode": "USD" }
            }
          ]
        }
      ],
      "price": {
        "subtotal": { "amount": 110, "currencyCode": "MYR" },
        "shipping": { "amount": 0, "currencyCode": "MYR" },
        "taxes": { "amount": 0, "currencyCode": "MYR" },
        "total": { "amount": 110, "currencyCode": "MYR" },
        "discounts": []
      }
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

Key data Fields

FieldTypeDescription
idstring (GID)Shopify Order Identity GID for the completed order (gid://shopify/OrderIdentity/...).
cart.tokenstringOpaque cart token identifying the cart this purchase originated from.
cart.linesarrayThe purchased line items. See fields below.
cart.priceobjectOrder-level price breakdown. See fields below.
cart.lines[*]
FieldTypeDescription
merchandiseIdstring (GID)Shopify ProductVariant GID for the purchased variant.
productIdstring (GID)Shopify Product GID for the purchased product.
titlestringProduct title at time of purchase.
quantitynumberQuantity purchased.
priceobjectPer-unit price as { "amount": <number>, "currencyCode": <string> }.
imageobjectProduct image with altText and sm / md / lg thumbnail URLs (64px / 128px / 256px).
discountsarrayDiscounts applied to this line. Empty when none apply. See discount fields below.
cart.price
FieldTypeDescription
subtotalobjectSum of line item prices before shipping and taxes, as { "amount": <number>, "currencyCode": <string> }.
shippingobjectShipping cost.
taxesobjectTotal taxes.
totalobjectGrand total charged to the shopper.
discountsarrayCart-level discounts applied to the order. Empty when none apply. See discount fields below.
Discount fields

Both cart.lines[*].discounts and cart.price.discounts use the same shape:

FieldTypeDescription
titlestringDiscount code or name (e.g. the code entered at checkout).
applicationTypestringHow the discount was applied (e.g. "code").
valuenumberThe discount value (e.g. 15 for a 15% discount).
valueTypestringHow value is interpreted (e.g. "percentage").
amountobjectThe resolved monetary discount as { "amount": <number>, "currencyCode": <string> }.

pushOpened

Fired when a shopper opens a push notification sent via Tapcart's push notification feature. Use this to measure push notification engagement and conversion.

Schema

{
  "event": "pushOpened",
  "data": {
    "actionId": "expo.modules.notifications.actions.DEFAULT",
    "data": {
      "aps": {
        "alert": {
          "title": "Push notification title",
					"body": "Push notification body"
        }
      },
      "destination": {
        "type": "internal",
				"url": "/products?id=123456"
      },
			"id": "123456",
      "payload": {
        "attachment": "https://cdn.shopify.com/...",
        "notification_id": "123456",
        "segment_id": "123456",
				"type": "product"
			}
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
data.aps.alert.titlestringThe title (main content) of the push notification
data.aps.alert.bodystringThe body (secondary content) of the push notification
data.destination.typestring
data.destination.urlstringThe internal destination url of the push. This is where the user will land in app after opening the push.
data.idstringThe primary identifier for the push.
data.payload.attachmentstringIf the push includes visual content, it will be sourced from this url.
data.payload.notification_idstringThe primary identifier for the push.
data.payload.segment_idstringThe primary identifier for the customer segment which was targeted by this push.
data.payload.typestring


search

Fired when a shopper submits a search query in the app's search bar or a search block. Use this to understand popular search terms and identify catalog gaps.

Schema

{
  "event": "search",
  "data": {
    "query": "Tank ",
    "metadata": {
      "blockId": "000000000000000000000001",
      "layoutId": "000000000000000000000002"
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
querystringThe raw search string entered by the shopper. May include trailing whitespace; trim before processing.
metadataobjectIdentifies the search UI component that triggered the event. May be absent on events from older app versions.
metadata.blockIdstringThe Tapcart content block ID of the search component.
metadata.layoutIdstringThe Tapcart layout ID containing the search component.

wishlistItemAdded

Fired when a shopper saves a product variant to a Tapcart native wishlist. The data.itemDetail field contains a product and variant summary drawn from Shopify data.

Schema

{
  "event": "wishlistItemAdded",
  "data": {
    "wishlistId": "000000000000000000000003",
    "wishlistType": "tapcartNative",
    "itemType": "variant",
    "itemDetail": {
      "product_id": "1000000000005",
      "variant_id": "20000000000005",
      "product_name": "Example Graphic T-Shirt",
      "product_title": "Example Graphic T-Shirt",
      "product_url": "https://yourstore.myshopify.com/products/example-graphic-tshirt-black",
      "product_image_url": "https://cdn.shopify.com/...",
      "sku": "EXAMPLE-SKU-001",
      "vendor": "Example Vendor",
      "variant_name": "L / Black",
      "variant_price": 7,
      "variant_compare_at_price": 50,
      "currency": "USD",
      "multi_currency_code": "USD",
      "available_for_sale": true,
      "variant_option_names": ["Size", "Color"],
      "variant_option_values": ["L", "Black"],
      "tags": ["best seller", "sale"],
      "updated_at": "2026-04-24T21:03:43.708Z"
    }
  },
  "properties": { ... },
  "mp_metadata": { ... }
}

data Fields

FieldTypeDescription
wishlistIdstringTapcart internal identifier for the wishlist this item was added to.
wishlistTypestringThe wishlist implementation type. "tapcartNative" indicates Tapcart's built-in wishlist feature.
itemTypestringThe granularity of the wishlisted item. "variant" means the specific variant (including option selections) was saved, not just the parent product.

data.itemDetail Fields

FieldTypeDescription
product_idstringNumeric Shopify Product ID (without GID prefix).
variant_idstringNumeric Shopify ProductVariant ID (without GID prefix).
product_name / product_titlestringProduct title. Both carry the same value.
product_urlstring (URL)Canonical Shopify storefront URL for the product.
product_image_urlstring (URL)URL of the product's featured image.
skustringSKU of the wishlisted variant.
vendorstringProduct vendor.
variant_namestringHuman-readable variant label, combining all selected option values (e.g. "L / Black").
variant_pricenumberCurrent selling price of the variant (numeric, not a decimal string).
variant_compare_at_pricenumberCompare-at (original) price of the variant.
currencystringISO 4217 currency code for the displayed prices.
multi_currency_codestringCurrency in which the variant is displayed to this shopper. Typically matches currency.
available_for_salebooleanWhether this variant is currently purchasable.
variant_option_namesstring[]Names of the product options in order (e.g. ["Size", "Color"]).
variant_option_valuesstring[]Selected values for each option, in the same order as variant_option_names (e.g. ["L", "Black"]).
tagsstring[]Shopify product tags on the parent product.
updated_atstring (ISO 8601)Timestamp of when this wishlist item was recorded in Tapcart's system.