Heap
Heap (now part of Contentsquare) is a product
analytics platform with auto-capture and retroactive event definitions.
This destination loads the Heap snippet from Heap's CDN and forwards
walkerOS events through heap.track(name, properties), plus identity,
user properties, persistent event properties, and runtime consent.
Heap is a web destination in the walkerOS flow:
Installation
npm install @walkeros/web-destination-heap- Integrated
- Bundled
import { startFlow } from '@walkeros/collector';
import { destinationHeap } from '@walkeros/web-destination-heap';
await startFlow({
destinations: {
heap: {
code: destinationHeap,
config: {
loadScript: true,
settings: {
appId: 'YOUR_HEAP_APP_ID',
},
},
},
},
});Add to your flow.json destinations:
"destinations": {
"heap": {
"package": "@walkeros/web-destination-heap",
"config": {
"loadScript": true,
"settings": {
"appId": "YOUR_HEAP_APP_ID"
}
}
}
}Configuration
This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.
Settings
| Property | Type | Description | More |
|---|---|---|---|
appId | string | Heap App ID. Find it in your Heap project under Settings > App ID. | |
disableTextCapture | boolean | Disable Heap auto text capture. Default: true. | |
disablePageviewAutocapture | boolean | Disable Heap automatic pageview tracking. Default: true (walkerOS sources handle pageviews). | |
disableSessionReplay | boolean | Disable Heap session replay. | |
secureCookie | boolean | SSL-only cookies. | |
ingestServer | string | Custom server endpoint for proxying Heap data. | |
identify | any | Destination-level identity mapping. Resolves to a string for heap.identify(). Example: { "key": "user.id" }. | |
userProperties | any | Destination-level user properties mapping. Resolves to object for heap.addUserProperties(). Example: { "map": { "plan": "data.plan" } }. |
Mapping
Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.
| Property | Type | Description | More |
|---|---|---|---|
identify | any | Per-event identity. Resolves to a string for heap.identify(). Example: { "key": "data.email" }. | |
reset | any | Reset Heap identity on this event. Set to true to call heap.resetIdentity(). | |
userProperties | any | Per-event user properties. Resolves to object for heap.addUserProperties(). | |
eventProperties | any | Per-event persistent event properties. Resolves to object for heap.addEventProperties() (persisted across page loads). | |
clearEventProperties | any | Clear all persistent event properties. Set to true to call heap.clearEventProperties(). |
Examples
Consent granted
A walker consent grant for analytics calls heap.startTracking to resume event capture.
{
"analytics": true
}heap.startTracking()Consent revoked
After analytics consent is granted (Heap loads and starts tracking), revoking it calls heap.stopTracking to pause event capture.
{
"analytics": false
}heap.startTracking();
heap.stopTracking()Default track
A walker event becomes a Heap track call with the event name and empty properties.
{
"name": "product view",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"detail",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [],
"consent": {
"functional": true
},
"id": "52decc61e3898cf4",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000100,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}heap.track("product view", {})Destination identify
Destination-level identify calls heap.identify with the user id before firing the default track.
{
"name": "page view",
"data": {
"domain": "www.example.com",
"title": "walkerOS documentation",
"referrer": "https://www.walkeros.io/",
"search": "?foo=bar",
"hash": "#hash",
"id": "/docs/"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "f0508d24c17aee87",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000102,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}heap.identify("us3r");
heap.track("page view", {})Renamed purchase
An order complete is renamed to purchase and mapped to Heap track properties such as order_id, total, and currency.
{
"name": "order complete",
"data": {
"id": "0rd3r1d",
"currency": "EUR",
"shipping": 5.22,
"taxes": 73.76,
"total": 555
},
"context": {
"shopping": [
"complete",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "product",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "product",
"data": {
"id": "cc",
"name": "Cool Cap",
"size": "one size",
"price": 42
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "gift",
"data": {
"name": "Surprise"
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
}
],
"consent": {
"functional": true
},
"id": "56e2a8f2a4365067",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000101,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"name": "purchase",
"data": {
"map": {
"order_id": "data.id",
"total": "data.total",
"currency": {
"key": "data.currency",
"value": "EUR"
}
}
}
}heap.track("purchase", {
"order_id": "0rd3r1d",
"total": 555,
"currency": "EUR"
})User properties on event
An order fires Heap addUserProperties with last-order fields and then tracks the event.
{
"name": "order complete",
"data": {
"id": "0rd3r1d",
"total": 555,
"currency": "EUR"
},
"context": {
"shopping": [
"complete",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "product",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "product",
"data": {
"id": "cc",
"name": "Cool Cap",
"size": "one size",
"price": 42
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "gift",
"data": {
"name": "Surprise"
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
}
],
"consent": {
"functional": true
},
"id": "1a016a1c3afc2142",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000105,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"settings": {
"userProperties": {
"map": {
"last_order_value": "data.total",
"last_order_currency": "data.currency"
}
}
}
}heap.addUserProperties({
"last_order_value": 555,
"last_order_currency": "EUR"
});
heap.track("order complete", {})Global event properties
A page view sets persistent Heap event properties so all subsequent events include the page category.
{
"name": "page view",
"data": {
"category": "docs"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "27fdbff0600ec5e0",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000106,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"eventProperties": {
"map": {
"page_category": "data.category"
}
}
}
}heap.addEventProperties({
"page_category": "docs"
})User login identify
A user login identifies the Heap user by email and adds user properties while skipping the track.
{
"name": "user login",
"data": {
"email": "user@example.com",
"plan": "premium",
"company": "Acme"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "270701d89326fddc",
"trigger": "test",
"entity": "user",
"action": "login",
"timestamp": 1700000103,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"identify": "data.email",
"userProperties": {
"map": {
"plan": "data.plan",
"company": "data.company"
}
}
}
}heap.identify("user@example.com");
heap.addUserProperties({
"plan": "premium",
"company": "Acme"
})User logout reset
A user logout calls heap.resetIdentity to clear the identified user from the Heap client.
{
"name": "user logout",
"data": {
"string": "foo",
"number": 1,
"boolean": true,
"array": [
0,
"text",
false
]
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "dd085b63477bcc1d",
"trigger": "test",
"entity": "user",
"action": "logout",
"timestamp": 1700000104,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"reset": true
}
}heap.resetIdentity()Consent
The destination wires walkerOS config.consent to Heap's runtime consent
API. heap.startTracking() fires when all required consent keys are
granted; heap.stopTracking() fires otherwise.
destinations: {
heap: {
code: destinationHeap,
config: {
consent: { analytics: true },
settings: { appId: 'YOUR_HEAP_APP_ID' },
},
},
}