Webchat Tracking API
The Webchat Tracking API lets you send visitor behavioral signals to Filum's AI Agent. When the AI Agent is configured with proactive engagement skills, it uses these signals to understand customer intent and start conversations at the right moment — for example, helping a customer who's comparing products or browsing out-of-stock items.
Prerequisites
- Webchat JS SDK v2 must be installed and initialized on your website
- The chat widget must be attached and fully loaded before calling
track() - The visitor must have an active session (i.e., they have interacted with the chat at least once)
- Tracking only works in embedded widget mode (standard website installation or React Native WebView) — it is not available in standalone mode
Quick Start
// Track a page view
window.filumChat.track([{
type: 'page_view',
url: 'https://yourstore.com/products/wireless-headphones',
pageType: 'product',
productId: 'SKU-001',
}]);
The SDK automatically adds a timestamp (ISO 8601) to each event.
track(events)
Send behavioral tracking events.
window.filumChat.track([event1, event2, event3]);
Parameters:
| Name | Type | Description |
|---|---|---|
events | TrackingEvent[] | An array of events |
Returns: boolean — true if the events were dispatched to the widget, false if the widget is not ready.
Event Types
page_view
Fires when a visitor views a page. The AI Agent uses sequences of page_view events to infer comparison behavior (e.g., switching back and forth between product pages).
window.filumChat.track([{
type: 'page_view',
url: 'https://yourstore.com/products/sony-wh1000xm5',
pageType: 'product', // 'blog' | 'category' | 'product' | any string
productId: 'SKU-WH1000XM5', // only for product pages
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'page_view' |
url | string | Yes | The absolute page URL (e.g. https://yourstore.com/products/...) |
pageType | string | No | Type of page: 'blog', 'category', 'product', or custom |
productId | string | No | Product identifier (when pageType is 'product') |
dwell
Indicates how long a visitor stayed on a page. Useful for detecting research intent (e.g., reading a buying guide for 2+ minutes).
window.filumChat.track([{
type: 'dwell',
url: 'https://yourstore.com/blog/best-headphones-2025',
pageType: 'blog',
durationSeconds: 120,
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'dwell' |
url | string | Yes | The absolute page URL |
pageType | string | No | Type of page |
durationSeconds | number | Yes | How long the visitor stayed (in seconds) |
product_status
Reports the stock status of a product page the visitor is viewing. Combined with dwell, this helps detect when a customer is looking at an out-of-stock item.
window.filumChat.track([{
type: 'product_status',
productId: 'SKU-APMAX2',
status: 'out_of_stock',
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'product_status' |
productId | string | Yes | Product identifier |
status | string | Yes | 'in_stock', 'out_of_stock', or custom status |
filter_usage
Fires when a visitor uses filters on a category or search page. Sorting by price low-to-high, for example, signals value-seeking intent.
window.filumChat.track([{
type: 'filter_usage',
category: 'Air Conditioners',
filterType: 'price',
filterValue: 'low_to_high',
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'filter_usage' |
category | string | No | The category being browsed |
filterType | string | Yes | Type of filter: 'price', 'brand', 'color', etc. |
filterValue | string | Yes | The selected filter value |
cart_action
Fires when a visitor adds or removes an item from their cart. Combined with search_event, this helps detect bundle intent.
window.filumChat.track([{
type: 'cart_action',
action: 'add',
productId: 'SKU-WH1000XM5',
productName: 'Sony WH-1000XM5',
category: 'Headphones',
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'cart_action' |
action | string | Yes | 'add' or 'remove' |
productId | string | Yes | Product identifier |
variantId | string | No | Variant identifier (size, color, etc.) |
productName | string | No | Human-readable product name |
category | string | No | Product category |
search_event
Fires when a visitor searches for products. Combined with cart_action, this helps the AI detect bundle intent (e.g., customer added a stove, now searching for range hoods).
window.filumChat.track([{
type: 'search_event',
query: 'range hood 90cm',
pageContext: 'https://yourstore.com/search',
categoryContext: 'Kitchen Appliances',
}]);
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be 'search_event' |
query | string | Yes | The search query text |
pageContext | string | No | Current page URL (absolute) |
categoryContext | string | No | Current category context |
Batching Events
You can send multiple events in a single call. This is useful when several signals fire at the same time — for example, viewing an out-of-stock product triggers both a page_view and a product_status event:
window.filumChat.track([
{
type: 'page_view',
url: 'https://yourstore.com/products/airpods-max-2',
pageType: 'product',
productId: 'SKU-APMAX2',
},
{
type: 'product_status',
productId: 'SKU-APMAX2',
status: 'out_of_stock',
},
]);
Integration Examples
Shopify / E-commerce: Track product page views
// On every product page
window.filumChat.track([{
type: 'page_view',
url: window.location.href,
pageType: 'product',
productId: document.querySelector('[data-product-id]')?.dataset.productId,
}]);
Shopify: Track add-to-cart
// Listen for Shopify's add-to-cart event
document.addEventListener('cart:item-added', (event) => {
const item = event.detail;
window.filumChat.track([{
type: 'cart_action',
action: 'add',
productId: String(item.product_id),
variantId: String(item.variant_id),
productName: item.product_title,
}]);
});
Track dwell time with a timer
let dwellStart = Date.now();
window.addEventListener('beforeunload', () => {
const durationSeconds = Math.round((Date.now() - dwellStart) / 1000);
if (durationSeconds > 5) {
window.filumChat?.track([{
type: 'dwell',
url: window.location.href,
pageType: 'product', // adjust based on your page
durationSeconds,
}]);
}
});
TypeScript Reference
type TrackingEventType =
| 'page_view'
| 'dwell'
| 'product_status'
| 'filter_usage'
| 'cart_action'
| 'search_event';
interface PageViewEvent {
type: 'page_view';
url: string;
pageType?: 'blog' | 'category' | 'product' | string;
productId?: string;
}
interface DwellEvent {
type: 'dwell';
url: string;
pageType?: 'blog' | 'category' | 'product' | string;
durationSeconds: number;
}
interface ProductStatusEvent {
type: 'product_status';
productId: string;
status: 'in_stock' | 'out_of_stock' | string;
}
interface FilterUsageEvent {
type: 'filter_usage';
category?: string;
filterType: string;
filterValue: string;
}
interface CartActionEvent {
type: 'cart_action';
action: 'add' | 'remove';
productId: string;
variantId?: string;
productName?: string;
category?: string;
}
interface SearchEventData {
type: 'search_event';
query: string;
pageContext?: string;
categoryContext?: string;
}
type TrackingEvent =
| PageViewEvent
| DwellEvent
| ProductStatusEvent
| FilterUsageEvent
| CartActionEvent
| SearchEventData;
Notes
- Session required:
track()requires an active chat session to be flushed to the server. Events received before a session is established remain buffered in-memory and are sent with the next flush once the session is ready. - Batching and delivery delay: The widget does not send events to the server on every
track()call. Events are pooled in-memory and flushed in a single batched request every 60 seconds. Expect up to ~60s of delivery delay per event; thetimestampattached at call time is what the AI Agent uses for ordering and dwell calculations, so this delay does not affect analysis. - Automatic
page_viewtracking: The widget automatically emits apage_viewevent whenever the host page URL changes (detected via the SDK's internal host-URL notification). These events are pushed into the same batch queue as explicittrack()calls, so you do not need to manually calltrack([{ type: 'page_view', ... }])on navigation. Consecutive notifications carrying the same URL are deduped. If the host page exposes product metadata (name/price), the automatic event is enriched withpageType: 'product'andproductId. - Timestamps: The SDK automatically adds an ISO 8601
timestampto every event at the momenttrack()is called. You do not need to include one. - Internal messages: Tracking events are sent as internal messages. They are not visible to the customer in the chat widget, nor to agents in the platform conversation view.
- Rate limiting: The server applies the same rate limit as regular messages (30 per minute). Because events are batched into a single request per minute, typical usage stays well under this limit regardless of
track()call frequency.
Support
Please contact the Filum Engineering Team if you encounter any issues with the Tracking API.