@brunoofarias/heatmap-collector
v0.1.2
Published
Lightweight TypeScript library to capture user interaction events and generate normalized heatmap data for AdTech environments.
Maintainers
Readme
heatmap-collector
A lightweight TypeScript library that captures user interaction events inside a specific HTML element and generates normalized heatmap data.
Designed for AdTech environments — ads, banners, iframes, landing pages, creative previews, and publisher pages — where performance, privacy, and small bundle size are critical.
Installation
npm install @brunoofarias/heatmap-collectorBasic usage
import { createHeatmapCollector } from '@brunoofarias/heatmap-collector';
const collector = createHeatmapCollector({
target: '#ad-container',
endpoint: 'https://collector.example.com/events',
mousemoveThrottleMs: 100,
flushIntervalMs: 5000,
maxBatchSize: 100,
metadata: {
campaignId: 'cmp_123',
creativeId: 'crt_456',
bidId: 'bid_789',
},
});
collector.start();AdTech usage
const collector = createHeatmapCollector({
target: document.querySelector('#banner')!,
endpoint: 'https://collector.example.com/heatmap',
transport: 'beacon',
flushIntervalMs: 3000,
maxBatchSize: 50,
metadata: {
accountId: 'acc_123',
campaignId: 'cmp_123',
adGroupId: 'ag_123',
adId: 'ad_123',
creativeId: 'crt_456',
bidId: 'bid_789',
exchangeId: 'adx',
publisherId: 'pub_123',
placementId: 'plc_123',
},
});
collector.start();Configuration options
| Option | Type | Default | Description |
|---|---|---|---|
| target | string \| HTMLElement | — | Required. CSS selector or element to observe. |
| endpoint | string | — | URL to send events to. Required unless using customTransport. |
| enabled | boolean | true | Disables the collector entirely when false. |
| autoStart | boolean | false | Start collecting immediately on creation. |
| collectMouseMove | boolean | true | Capture mousemove events. |
| collectClicks | boolean | true | Capture click events. |
| collectTouch | boolean | true | Capture touchstart and touchmove events. |
| collectHover | boolean | false | Capture mouseenter and mouseleave events. |
| sampleRate | number | 1 | Fraction of events to collect, between 0 and 1. |
| mousemoveThrottleMs | number | 100 | Minimum ms between mousemove captures. |
| touchmoveThrottleMs | number | 100 | Minimum ms between touchmove captures. |
| flushIntervalMs | number | 5000 | How often (ms) to flush the queue automatically. |
| maxBatchSize | number | 100 | Flush when the queue reaches this size. |
| sessionId | string | — | Optional session identifier included in every payload. |
| anonymousId | string | — | Optional anonymous user identifier. |
| metadata | Record<string, string \| number \| boolean \| null> | — | Custom metadata included in every payload. |
| transport | 'fetch' \| 'beacon' \| 'custom' | 'beacon' | Transport mechanism. |
| customTransport | (payload) => Promise<void> \| void | — | Required when transport is 'custom'. |
| debug | boolean | false | Log transport errors and warnings to the console. |
Lifecycle API
collector.start(); // Attach listeners and start flush timer
collector.stop(); // Remove listeners and stop flush timer (keeps queue)
await collector.flush(); // Send queued events immediately
collector.destroy(); // Stop, clear queue, remove all references
collector.getQueueSize(); // Returns number of events currently queuedTransport examples
fetch
createHeatmapCollector({
target: '#ad',
endpoint: 'https://collector.example.com/events',
transport: 'fetch',
});beacon (default)
createHeatmapCollector({
target: '#ad',
endpoint: 'https://collector.example.com/events',
transport: 'beacon',
});navigator.sendBeacon is preferred for page-unload scenarios. Falls back to fetch when unavailable.
custom
createHeatmapCollector({
target: '#ad',
transport: 'custom',
customTransport: async (payload) => {
await mySDK.track('heatmap', payload);
},
});Payload schema
{
"library": {
"name": "heatmap-collector",
"version": "0.1.0"
},
"context": {
"sessionId": "session_123",
"anonymousId": "anon_456",
"targetWidth": 300,
"targetHeight": 250,
"url": "https://example.com/page"
},
"metadata": {
"campaignId": "cmp_123",
"creativeId": "crt_456",
"bidId": "bid_789"
},
"events": [
{
"type": "mousemove",
"x": 120,
"y": 80,
"normalizedX": 0.4,
"normalizedY": 0.32,
"timestamp": 1710000000000,
"targetWidth": 300,
"targetHeight": 250
}
]
}Privacy boundaries
The library is designed to be safe in privacy-sensitive environments.
What it collects:
- Event type (
mousemove,click,touchstart,touchmove,mouseenter,mouseleave) - Pointer coordinates relative to the target element
- Normalized coordinates (0–1 range)
- Target element dimensions at the time of the event
- Unix timestamp
- Explicitly provided metadata (you control what goes in)
What it never collects:
- Input field values
- Text content from the DOM
- Cookies
localStorageorsessionStorage- Full DOM structure or element attributes
- Browser fingerprint
- Any data from outside the configured target element
Performance considerations
mousemoveandtouchmoveevents are throttled (default: 100ms) to reduce CPU load.- Events are batched in memory and sent in bulk, minimizing network calls.
- Event handlers perform minimal synchronous work — only coordinate math and a queue push.
getBoundingClientRect()is called per event; avoid extremely high-frequency events in performance-critical contexts by tuningmousemoveThrottleMs.- No external runtime dependencies.
- The library flushes automatically on
visibilitychange(page hidden) andpagehideto avoid data loss.
License
MIT
