Skip to main content
Ask your AI

Heap

Web Source code Package Beta

Heap (now part of Contentsquare) is a product analytics platform with auto-capture and retroactive event definitions. With loadScript: true, this destination loads the Heap script from Heap's CDN. It forwards walkerOS events through heap.track(name, properties), plus identity, user properties, persistent event properties, and runtime consent.

Where this fits

Heap is a web destination in the walkerOS flow:

Installation​

npm install @walkeros/web-destination-heap
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',
        },
      },
    },
  },
});
caution

loadScript: true loads the classic Heap SDK (https://cdn.heapanalytics.com/js/heap-<appId>.js). Events pushed while the script loads wait for it and reach Heap once it is ready; if the script is blocked or fails to load, those and later pushes fail with vendor-not-loaded and show up as failed events. disableTextCapture (default true), secureCookie and further SDK options in heapConfig go into the config the classic SDK reads when it loads, so they apply only with loadScript: true. Without loadScript the destination ignores them and nothing reports it: set these options in your own Heap snippet. The classic SDK has no switch to stop tracking, so a consent revocation stops the events walkerOS sends but not Heap's own autocapture (see Consent).

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​

PropertyTypeDescriptionMore
appId*stringHeap App ID. Find it in your Heap project under Settings > App ID.
disableTextCapturebooleanDisable Heap auto text capture. Default: true. Applied only with loadScript: true, in the config the classic Heap SDK reads when it loads; with your own Heap snippet, set it there.
secureCookiebooleanSSL-only cookies. Applied only with loadScript: true, in the config the classic Heap SDK reads when it loads.
heapConfigRecord<string, any>Additional options for the classic Heap SDK, merged over disableTextCapture and secureCookie. Applied only with loadScript: true. Example: { "trackingServer": "https://heap.example.com" }.
identifyanyDestination-level identity mapping. Resolves to a string for heap.identify(). Example: { "key": "user.id" }.
userPropertiesanyDestination-level user properties mapping. Resolves to object for heap.addUserProperties(). Example: { "map": { "plan": "data.plan" } }.
* Required fields

Mapping​

Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

PropertyTypeDescriptionMore
identifyanyPer-event identity. Resolves to a string for heap.identify(). Example: { "key": "data.email" }.
resetanyReset Heap identity on this event. Set to true to call heap.resetIdentity().
userPropertiesanyPer-event user properties. Resolves to object for heap.addUserProperties().
eventPropertiesanyPer-event persistent event properties. Resolves to object for heap.addEventProperties() (persisted across page loads).
clearEventPropertiesanyClear all persistent event properties. Set to true to call heap.clearEventProperties().

Examples

Consent granted

With consent: { analytics: true } in the destination config, a walker consent grant for analytics calls heap.startTracking.

Event
{
  "analytics": true
}
Out
window.heap.startTracking()

Consent revoked

With consent: { analytics: true } in the destination config, a revocation of analytics calls heap.stopTracking once Heap has loaded. The classic Heap SDK that loadScript loads has no such method, so there only the pushes stop.

Event
{
  "analytics": false
}
Out
window.heap.stopTracking()

Default track

A walker event becomes a Heap track call with the event name and empty properties.

Event
{
  "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": "db22fb16c70f663d",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000100,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Out
window.heap.track("product view", {})

Destination identify

With settings.identify set to 'user.id', the destination calls heap.identify before the default track.

Event
{
  "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": "f0cc5f6fec3d8eeb",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000102,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Out
window.heap.identify("us3r");

window.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.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "value": 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": "235d0d7bd7a213f2",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000101,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "purchase",
  "data": {
    "map": {
      "order_id": "data.id",
      "total": "data.value",
      "currency": {
        "key": "data.currency",
        "value": "EUR"
      }
    }
  }
}
Out
window.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.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "value": 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": "235d0d7bd7a213f2",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000105,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "settings": {
    "userProperties": {
      "map": {
        "last_order_value": "data.value",
        "last_order_currency": "data.currency"
      }
    }
  }
}
Out
window.heap.addUserProperties({
  "last_order_value": 555,
  "last_order_currency": "EUR"
});

window.heap.track("order complete", {})

Global event properties

A page view sets persistent Heap event properties so all subsequent events include the page category.

Event
{
  "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": "f0cc5f6fec3d8eeb",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000106,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "silent": true,
  "settings": {
    "eventProperties": {
      "map": {
        "page_category": "data.category"
      }
    }
  }
}
Out
window.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.

Event
{
  "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": "47f07df3d8014322",
  "trigger": "test",
  "entity": "user",
  "action": "login",
  "timestamp": 1700000103,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "silent": true,
  "settings": {
    "identify": "data.email",
    "userProperties": {
      "map": {
        "plan": "data.plan",
        "company": "data.company"
      }
    }
  }
}
Out
window.heap.identify("user@example.com");

window.heap.addUserProperties({
  "plan": "premium",
  "company": "Acme"
})

User logout reset

A user logout calls heap.resetIdentity to clear the identified user from the Heap client.

Event
{
  "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": "9fb90fbd8836eb19",
  "trigger": "test",
  "entity": "user",
  "action": "logout",
  "timestamp": 1700000104,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "silent": true,
  "settings": {
    "reset": true
  }
}
Out
window.heap.resetIdentity()

With config.consent declared, the collector initializes the destination, and with loadScript: true loads Heap's script, only once one of the required consent keys is granted (see consent management). On each consent command that names a required key, once Heap has loaded, the destination calls heap.startTracking() while the required consent is granted (one granted key is enough) and heap.stopTracking() otherwise.

The classic SDK that loadScript: true loads has neither method, so the destination calls neither. A revocation then only stops the events walkerOS sends: Heap's own autocapture keeps running because the classic SDK cannot be switched off. To keep Heap from capturing before consent, load Heap's script only after consent is granted, which is what config.consent does with loadScript: true.

destinations: {
  heap: {
    code: destinationHeap,
    config: {
      loadScript: true,
      consent: { analytics: true },
      settings: { appId: 'YOUR_HEAP_APP_ID' },
    },
  },
}
💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)