This article describes the data format required when the Crescendo Web SDK receives behavior events. If the data structure does not meet the specifications below, the event cannot be written to the system, resulting in broken tracking and failed automation triggers.
For installation, see: Tutorial | SDK Web Behavior Tracking Tool;
To check installation and event tracking status, see: Tutorial | Web SDK Installation Verification and Event Tracking Check
Table of Contents
The SDK currently supports the following three event types. All events are called using the same method:
clWidget.clSdk.clRe.record("event_name", { props: { ... } });| Event Name | Trigger Timing | Required Fields |
|---|---|---|
page_view |
User enters any page |
page_path, page_title
|
add_to_cart |
User adds an item to the cart |
items (including item_id, item_name, price, quantity) |
remove_from_cart |
User removes an item from the cart | Same as add_to_cart
|
purchase |
User completes checkout and payment |
transaction_id, revenue, items
|
page_view|Page View
Triggered when a user enters any page. page_view is also the first validation metric to confirm after installation is complete.
Field Specifications
| Field | Type | Required | Description |
|---|---|---|---|
props.page_path |
String | Required | The URL path of the current page, e.g. /products/shirt
|
props.page_title |
String | Required | The <title> text of the current page |
Code Example
clWidget.clSdk.clRe.record("page_view", {
props: {
page_path: "/products/shirt",
page_title: "Summer Cotton T-Shirt | Brand Official Site",
},
});add_to_cart / remove_from_cart|Cart Events
Triggered when an item is added to or removed from the cart. Both events use exactly the same data structure; only the event name differs.
Event-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
props.items |
Array | Required | Array of items; must contain at least one item object |
props.currency |
String | Optional | Currency code (ISO 4217), e.g. TWD, USD
|
items Array — Fields for Each Item Object
| Field | Type | Required | Description |
|---|---|---|---|
item_id |
String | Required | Unique product identifier (SKU or product ID) |
item_name |
String | Required | Product name |
price |
Number | Required | Unit price; must be a Number type (do not send the string "490"). This field is also required data for the dynamic cards in Cart Retargeting, so make sure it is not empty. |
quantity |
Number | Required | Quantity; must be a Number type |
description |
String | Optional | Product description text |
affiliation |
String | Optional | Brand or store affiliation name |
coupon |
String | Optional | Item-level coupon code |
discount |
Number | Optional | Item discount amount |
index |
Number | Optional | The item's position in the list (starting from 1) |
item_brand |
String | Optional | Product brand name |
item_category |
String | Optional | Product category (first level) |
item_category2 ~ 5 |
String | Optional | Product category (second to fifth level) |
item_list_id |
String | Optional | ID of the list the item belongs to |
item_list_name |
String | Optional | Name of the list the item belongs to |
item_variant |
String | Optional | Product variant (e.g. color, size) |
link |
String | Optional | Product page URL |
image_link |
String | Optional | Product image URL |
location_id |
String | Optional | Location ID of the item (Google Places ID format) |
Code Example
// Add to cart
clWidget.clSdk.clRe.record("add_to_cart", {
props: {
currency: "TWD",
items: [
{
item_id: "SKU_67890", // Required
item_name: "Summer Cotton T-Shirt", // Required
price: 490, // Required: Number, do not send "490" as a string
quantity: 1, // Required: Number
item_brand: "Brand Name",
item_category: "Apparel",
item_variant: "White / M",
link: "https://example.com/products/shirt",
image_link: "https://example.com/images/shirt.jpg",
},
],
},
});
// Remove from cart (same structure, only the event name differs)
clWidget.clSdk.clRe.record("remove_from_cart", {
props: {
currency: "TWD",
items: [
{
item_id: "SKU_67890",
item_name: "Summer Cotton T-Shirt",
price: 490,
quantity: 1,
},
],
},
});purchase|Purchase
Triggered after a user completes checkout and payment. This event is the core basis for Cart Retargeting and conversion tracking, so make sure all required fields are complete.
Event-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
props.transaction_id |
String | Required | Unique order identifier. The system uses this field for deduplication; sending the same ID again will not be counted twice |
props.revenue |
Number | Required | Total order amount; must be a Number type |
props.items |
Array | Required | Array of order items; field structure is the same as add_to_cart |
props.currency |
String | Optional | Currency code (ISO 4217), e.g. TWD
|
props.tax |
Number | Optional | Tax amount |
props.shipping |
Number | Optional | Shipping fee |
props.coupon |
String | Optional | Order-level coupon code |
Code Example
clWidget.clSdk.clRe.record("purchase", {
props: {
transaction_id: "ORDER_20240101_001", // Required: order ID
revenue: 980, // Required: Number
currency: "TWD",
tax: 0,
shipping: 0,
coupon: "SUMMER_SALE",
items: [
{
item_id: "SKU_67890", // Required
item_name: "Summer Cotton T-Shirt", // Required
price: 490, // Required: Number
quantity: 2, // Required: Number
item_variant: "White / M",
},
],
},
});WebSDK Identify|Member Identity Resolution (Updated 2026.06)
After a visitor logs in or registers on your website, you can use WebSDK Identify to pass the member's identity to Crescendo, resolving the visitor's previously anonymous browsing footprint to an existing member. This is what enables accurate automated messaging and segmentation afterward.
It uses the same dataLayer mechanism as GA4: after a successful login or registration, simply push a clIdentity event to window.dataLayer. No additional API call is required.
User logs in → dataLayer.push(clIdentity) → SDK detects the event → Synced to MAAC → Precise marketing
clIdentity is pushed correctly. Path: Admin Center > Channel Settings > Website > General Settings.① What to do: push the event after a successful login or registration
Push the following event in a frontend flow where the identity has been confirmed (for example, a successful login callback). customerId is required; all other fields are optional. If customerId is not provided, the system will not create or update member data.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "clIdentity",
params: {
customerId: "REQUIRED_UNIQUE_ID", // Required: your platform's user ID
email: "user@example.com", // Optional
name: "John Doe", // Optional
phone: "+886912345678", // Optional (E.164 format)
gender: "male", // Optional (male/female/other/unknown)
birthday: "1995-01-01", // Optional (YYYY-MM-DD)
address: "123 Main St, ..." // Optional
}
});② Field Specifications
| Field | Required | Format / Notes | Mapped Field |
|---|---|---|---|
customerId |
Required | String; we recommend using a stable, unchanging member ID | customer_id |
email |
Optional | Must be a valid email format | display_email |
name |
Optional | String | display_name |
phone |
Optional |
Must include the country code (E.164 format), e.g. +886912345678; numbers without a country code are treated as invalid and skipped
|
display_mobile |
gender |
Optional | Accepts male, female, other, unknown
|
gender |
birthday |
Optional | Format is YYYY-MM-DD
|
birth |
address |
Optional | String | address |
gender is not one of the values above, phone is missing the country code, or birthday is not in YYYY-MM-DD format), the system will skip that field but still create/update the member. The whole record will not fail, and no error is returned. Please verify that each field is in the correct format before going live.③ When to Call
| Timing | Push clIdentity? | Description |
|---|---|---|
| Member login succeeds | ✅ Push | A stable member ID is available; this is the primary identification point |
| Member registration completes | ✅ Push | First-time identification of a new member |
| User logs out | ❌ Not required | The SDK automatically maintains the current identity; when switching users, simply push again once the new user logs in |
| Visitor browsing (not logged in) | ❌ Do not push | There is no stable customerId; do not push for anonymous visitors |
④ How to Confirm Identification Succeeded (Verification)
Member identity resolution is not covered by the "Event Tracking Check" tool. Please confirm it using the steps below:
- Confirm that "Website Tracking" is enabled for the Web Channel (see the precondition above).
- On the login/registration page, open the Console in your browser's developer tools, type
dataLayerto inspect it, and confirm that it contains aclIdentityevent withcustomerIdcorrectly populated. - Switch to the Network tab and confirm that a
POST /api/v1/authenticaterequest appears after login, with yourcustomer_idin the request payload. - Finally, contact the Crescendo Lab Customer Success team to help confirm whether the corresponding member data has been created/updated in the backend.
⑤ Notes and FAQs
I have pushed clIdentity, but I can't find the member data in the backend. What should I do?
This is usually not an "error" but rather a case where one of the conditions is not met, causing the record to be silently skipped (no error message is shown). Please check the following in order:
- Whether "Website Tracking" is enabled for the Web Channel — if not, the entire identify is skipped without an error (the most common cause).
- Whether the pushed
paramsincludecustomerId(required) — withoutcustomerId, no member is created or updated. - Whether the optional fields are in the correct format —
phonemust include the country code,gendermust be male/female/other/unknown, andbirthdaymust beYYYY-MM-DD; fields with invalid formats are skipped, but the remaining fields are still written. - Use the "④ How to Confirm Identification Succeeded" steps above to check the
clIdentityevent and thePOST /api/v1/authenticaterequest in the Console / Network tabs.
Reminder: Member identity resolution will not appear in the "Event Tracking Check" tool. Please contact the Crescendo Lab Customer Success team to confirm the member data in the backend instead.
What happens if I push the same customerId repeatedly?
The SDK automatically merges events with the same customerId, updating using a "new overwrites old, ignore empty values" rule, and only re-validates when the data changes. It will not create duplicate member records.
What should I do when a user logs out or switches accounts?
Logging out does not require calling any method; the SDK automatically maintains the current identity. When a new user logs in, simply push the new customerId, and the SDK will create the corresponding mapping automatically. (This avoids losing the mapping on page reload and is consistent with industry recommendations.)
Can customerId be changed afterward?
We do not recommend changing it. customerId is the primary identifier of a member's identity, and changing it will make it impossible to associate historical behavior data. Please use a stable, unchanging member ID as the customerId.
Will a failed clIdentity affect the website?
No. clIdentity is a non-blocking event; even if the subsequent API call fails, it will not affect the normal operation of the website itself. We recommend that developers add a try-catch to log it.
What happens if the same customerId is used on different devices?
They share the same member record and keep it updated; the user's browsing behavior across different devices can all be linked to the same member through the customerId.
Verifying That Events Are Sent Correctly
After implementing the tracking code, follow the steps below to verify it yourself, without waiting for support confirmation.
Step 1: Open your browser's developer tools
In Chrome, press F12 (on Mac, Cmd + Option + I), switch to the Console tab, and type datalayer to filter.
Step 2: Contact the Crescendo Lab Customer Success team for final confirmation
Once your own verification passes, contact the Crescendo Lab Customer Success team to confirm whether the backend has correctly received the following events:
-
page_view— entering any page -
add_to_cart— adding an item to the cart -
purchase— completing checkout, and confirm that thetransaction_idanditemsdata are correct
Common Error Reference
| Error Condition | Cause | Correct Approach |
|---|---|---|
| Event is sent but the backend receives no data |
items is sent as an empty array []
|
items must contain at least one item object |
| Product data is missing |
Any of item_id, item_name, price, quantity is missing |
Each item object must include these four required fields |
| purchase event cannot be matched to an order |
transaction_id or revenue was not provided
|
Both fields are required for purchase |
| Amount or quantity data is abnormal |
price, quantity, or revenue is sent as a string, e.g. "490"
|
Numeric fields must be sent as a Number type, e.g. 490
|
| Events are counted twice | Multiple event sources are enabled at the same time | Each website can use only one sending method |
SDK is not loaded; clWidget is undefined |
The GTM code was not published correctly, or the trigger conditions are misconfigured | Confirm that the GTM trigger condition is set to "DOM Ready" and that the container is published |
💬 Need further assistance?
Please contact the Crescendo Lab Customer Success team. Providing the following information can speed up troubleshooting:
- Installation type (self-hosted e-commerce / SHOPLINE / CYBERBIZ / Shopify / 91APP)
- Browser Console screenshot (whether any error messages appear)
- Payload screenshot of the record request in the Console tab