Skip to main content
Technology & EngineeringAnalytics Services184 lines

Heap

Heap: autocapture product analytics, session replay, retroactive event definition, funnel and retention analysis, JavaScript SDK

Quick Summary22 lines
You are an expert in integrating Heap for automatic product analytics with retroactive event definition.

## Key Points

- Use `heap.identify()` with a stable user ID (not email) so identity persists across sessions and devices. Call it on every page load for logged-in users.
- Set user properties for segmentation dimensions (plan, role, company) and event properties for session-scoped context (A/B test variant, referral source).
- Calling `heap.identify()` with different IDs for the same user creates duplicate user profiles that are difficult to merge. Always use a single canonical user ID.

## Quick Example

```bash
npm install @heap/heap-node
```

```html
<script type="text/javascript">
  window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.heapanalytics.com/js/heap-"+e+".js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a);for(var n=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","resetIdentity","removeEventProperty","setEventProperties","track","unsetEventProperty"],o=0;o<p.length;o++)heap[p[o]]=n(p[o])};
  heap.load("YOUR_APP_ID");
</script>
```
skilldb get analytics-services-skills/HeapFull skill: 184 lines
Paste into your CLAUDE.md or agent config

Heap — Analytics Integration

You are an expert in integrating Heap for automatic product analytics with retroactive event definition.

Core Philosophy

Overview

Heap is a product analytics platform that automatically captures every user interaction (clicks, pageviews, form submissions, field changes) without requiring manual instrumentation. Events can be defined retroactively, meaning you can analyze past behavior without having pre-planned tracking. Heap also offers session replay, funnel analysis, retention charts, and user segmentation.

Setup & Configuration

Install via npm

npm install @heap/heap-node

Browser SDK (snippet-based)

Add the Heap snippet to your HTML <head>:

<script type="text/javascript">
  window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.heapanalytics.com/js/heap-"+e+".js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a);for(var n=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","resetIdentity","removeEventProperty","setEventProperties","track","unsetEventProperty"],o=0;o<p.length;o++)heap[p[o]]=n(p[o])};
  heap.load("YOUR_APP_ID");
</script>

React Integration

// lib/heap.ts
export function initHeap(appId: string) {
  if (typeof window === "undefined") return;
  (window as any).heap?.load(appId, {
    secureCookie: true,
    trackingServer: "https://heapanalytics.com",
  });
}

// app/layout.tsx (Next.js App Router)
"use client";
import { useEffect } from "react";
import { initHeap } from "@/lib/heap";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    initHeap(process.env.NEXT_PUBLIC_HEAP_APP_ID!);
  }, []);

  return <html><body>{children}</body></html>;
}

Server-Side with Node SDK

import Heap from "@heap/heap-node";

const heap = new Heap("YOUR_APP_ID");

// Track a server-side event
await heap.track({
  identity: "user-123",
  event: "subscription_created",
  properties: {
    plan: "pro",
    billingCycle: "annual",
    mrr: 99.0,
  },
});

// Add user properties server-side
await heap.addUserProperties({
  identity: "user-123",
  properties: {
    company: "Acme Corp",
    role: "admin",
  },
});

Core Patterns

Identifying Users

// Call identify after login or signup
heap.identify("user-123");

// Add user-level properties for segmentation
heap.addUserProperties({
  email: "user@example.com",
  plan: "enterprise",
  signupDate: "2025-03-10",
  companySize: "50-200",
});

Custom Event Tracking

While Heap autocaptures interactions, custom events are useful for business-logic events:

// Track a custom event with properties
heap.track("Checkout Completed", {
  orderId: "order-456",
  total: 149.99,
  itemCount: 3,
  couponUsed: true,
});

// Track feature adoption
heap.track("Feature Used", {
  featureName: "export-csv",
  context: "dashboard",
});

Event Properties (Session-Scoped)

// Set properties that attach to all subsequent events in the session
heap.addEventProperties({
  experimentGroup: "variant-b",
  abTestName: "onboarding-flow-v2",
});

// Remove a specific event property
heap.removeEventProperty("experimentGroup");

// Clear all event properties
heap.clearEventProperties();

SPA Route Change Tracking

Heap autocaptures SPA route changes, but you can enrich them:

// React Router integration
import { useLocation } from "react-router-dom";
import { useEffect } from "react";

function useHeapPageTracking() {
  const location = useLocation();

  useEffect(() => {
    heap.addEventProperties({
      currentSection: location.pathname.split("/")[1] || "home",
    });
  }, [location.pathname]);
}

Best Practices

  • Use heap.identify() with a stable user ID (not email) so identity persists across sessions and devices. Call it on every page load for logged-in users.
  • Define events retroactively in the Heap UI using the Visual Labeler rather than over-instrumenting with custom heap.track() calls. Reserve custom tracking for server-side or business-logic events that cannot be autocaptured.
  • Set user properties for segmentation dimensions (plan, role, company) and event properties for session-scoped context (A/B test variant, referral source).

Common Pitfalls

  • Calling heap.identify() with different IDs for the same user creates duplicate user profiles that are difficult to merge. Always use a single canonical user ID.
  • Heap autocapture relies on DOM element attributes. Dynamically generated class names (e.g., CSS-in-JS hashes) make it hard to define stable events in the Visual Labeler. Use data-heap-id attributes on key interactive elements to ensure reliable event definitions.

Anti-Patterns

Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.

Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.

Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.

Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.

Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.

Install this skill directly: skilldb add analytics-services-skills

Get CLI access →