Heap Setup & Implementation | OpsBlu Docs

Heap Setup & Implementation

How to deploy Heap analytics with autocapture tuning, custom event definitions, identity management, and server-side integration.

Heap's defining feature is autocapture: it records every click, pageview, form submission, and field change on your website without requiring explicit instrumentation for each event. This means you can retroactively define events and analyze behavior you did not anticipate needing to track. However, autocapture also means Heap captures everything -- including sensitive form data, PII in URLs, and irrelevant UI interactions that create noise. A proper implementation is not about adding tracking (Heap does that automatically) but about governing what gets captured, defining meaningful events from the captured data, and ensuring identity resolution works correctly.

Why Proper Implementation Matters

Autocapture is a Double-Edged Sword

The promise: You never miss an event. Product managers can retroactively analyze user behavior without filing engineering tickets.

The reality without governance:

  • Heap captures text content from DOM elements, which may include PII (names, emails, addresses displayed on screen)
  • URL parameters may contain sensitive data (session tokens, PII, API keys)
  • Every button click, link click, and form interaction is captured, creating thousands of unique events
  • Without named "Definitions" to organize autocaptured data, the event stream is unusable noise
  • Session Replay captures screen content that may include sensitive information

Identity Merge is Permanent

Like Amplitude, Heap's identity resolution has permanent consequences:

  • heap.identify('user-123') permanently associates the current anonymous session with user-123
  • If called at the wrong time (e.g., on a shared device without logout), all anonymous activity is attributed to the wrong user
  • There is no self-service way to un-merge identities
  • heap.resetIdentity() starts a new anonymous session but does not undo previous merges

Data Volume Affects Performance and Cost

Heap pricing is typically based on session volume. Autocapture means every session generates significantly more events than manually instrumented platforms:

  • A single page load might generate 20+ autocaptured events (pageview, element views, scroll events)
  • Forms with many fields generate separate events per field change
  • SPAs with frequent route changes generate more pageview events
  • Session Replay has separate storage and cost implications

Pre-Implementation Planning

Access and Permissions

Heap Account:

  1. Sign in at heapanalytics.com
  2. Verify your Heap environment (each environment has a separate App ID)
  3. Request Admin access for implementation work

Required Access:

Platform Role Purpose
Heap Admin App ID management, governance rules, data settings
Heap Architect Event definitions, user properties, data management
Website/App Developer Snippet installation, data layer integration
Server Developer Server-side API integration

Environment App IDs:

Environment App ID Purpose
Development 1234567890 Local/dev testing (separate data)
Production 0987654321 Live user data

Important: Use separate App IDs for development and production. Test data in your production environment permanently pollutes your analytics.

Data Governance Planning

Before installing Heap, decide what NOT to capture:

PII Suppression Rules:

Data Type Where It Appears Suppression Method
Email addresses Form fields, on-screen text CSS class heap-ignore on elements
Phone numbers Contact forms, profiles CSS class heap-ignore
Credit card numbers Payment forms CSS class heap-ignore + Heap built-in PII detection
Social Security numbers Sensitive forms Entire page exclusion
Passwords Login/registration forms Automatically suppressed by Heap
Medical information Health-related forms Page-level or section-level exclusion

URL Sanitization:

// Heap captures full URLs by default. Strip sensitive parameters:
heap.addEventProperties({
  'clean_url': window.location.pathname  // Path only, no query params
});

// Or configure Heap to ignore specific query parameters
// In Heap UI: Settings > Privacy > URL Query Parameter Blocklist
// Add: token, session_id, api_key, email, reset_token

Event Definition Strategy

Plan which autocaptured events to formalize as "Definitions":

Definition Name Type Autocapture Source Description
Signup Button Click Click Button with text "Sign Up" User clicks primary signup CTA
Pricing Page View Pageview URL contains /pricing User visits pricing page
Add to Cart Click Button with class .add-to-cart User adds product to cart
Checkout Started Pageview URL contains /checkout User enters checkout flow
Purchase Complete Custom (server) Server API event Order confirmed
Search Performed Submit Form with id search-form User performs site search

Implementation Walkthrough

Step 1: Install Heap Snippet

Direct Installation (place in <head> before closing </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", {
    secureCookie: true,           // Set Secure flag on cookies
    disableTextCapture: false,    // Set to true to stop capturing inner text
    // For consent management:
    // rewrite: function(event) { return event; }  // Transform events before sending
  });
</script>

With Consent Management (delayed initialization):

<script type="text/javascript">
  // Load Heap but don't start capturing until consent
  window.heap=window.heap||[];
  // ... (same loader code as above)

  heap.load("YOUR_APP_ID", {
    secureCookie: true,
    disableTextCapture: false
  });

  // Check consent status
  if (!hasAnalyticsConsent()) {
    // Heap is loaded but not yet tracking
    heap.stopTracking();  // Pause data collection
  }

  // When consent is granted:
  function onConsentGranted() {
    heap.startTracking();  // Resume data collection
  }
</script>

Via Google Tag Manager:

  1. Create a Custom HTML tag
  2. Paste the Heap snippet code
  3. Set trigger: All Pages (with consent condition if required)
  4. Ensure tag fires in the <head> section (tag sequencing: fire before other tags)

Step 2: Configure PII Suppression

CSS Class Method (recommended):

Add the heap-ignore class to any element containing PII:

<!-- Heap will NOT capture text or values from these elements -->
<input type="email" class="heap-ignore" placeholder="Email" />
<span class="heap-ignore">john.doe@example.com</span>
<div class="heap-ignore">
  <p>Customer: John Doe</p>
  <p>Phone: (555) 123-4567</p>
</div>

Redact entire page sections:

<div class="heap-ignore">
  <!-- Nothing inside this div will be captured by Heap -->
  <form id="sensitive-form">
    <input name="ssn" />
    <input name="medical_info" />
  </form>
</div>

Programmatic Suppression:

// In Heap Settings > Privacy, configure:
// 1. URL Query Parameter Blocklist: token, session_id, api_key, email
// 2. Text Capture Blocklist: Regex patterns for PII
// 3. Session Replay Privacy: Mask all input fields, block specific selectors

Step 3: Implement User Identity

// After successful authentication
function onUserLogin(user) {
  // Identify the user - merges anonymous session with user profile
  heap.identify(user.id);  // Use your internal user ID, NOT email

  // Set user properties
  heap.addUserProperties({
    'plan_type': user.plan,              // 'free', 'pro', 'enterprise'
    'company': user.company,
    'role': user.role,
    'signup_date': user.createdAt,
    'account_age_days': daysSince(user.createdAt)
  });
}

// On logout - prevent cross-user contamination
function onUserLogout() {
  heap.track('User Logged Out');
  heap.resetIdentity();  // Generates new anonymous identity
}

Identity Rules:

  • Call heap.identify() only after confirmed authentication
  • Use immutable internal user IDs (not emails, which change)
  • Always call heap.resetIdentity() on logout
  • For shared devices: Call resetIdentity() between users

Step 4: Track Custom Events

While autocapture handles most interactions, some events need explicit tracking:

// Revenue events (autocapture cannot access backend data)
heap.track('Purchase Completed', {
  order_id: 'ORD-2024-12345',
  revenue: 129.98,
  currency: 'USD',
  item_count: 2,
  coupon_code: 'SAVE10',
  payment_method: 'credit_card'
});

// Backend-triggered events
heap.track('Subscription Started', {
  plan_type: 'pro',
  billing_period: 'annual',
  mrr: 99.00,
  trial_converted: true
});

// Feature usage with context
heap.track('Report Generated', {
  report_type: 'monthly_analytics',
  date_range: '30d',
  export_format: 'pdf',
  row_count: 1500
});

// Set event-level properties that persist across events
heap.addEventProperties({
  'ab_test_variant': 'pricing_v2',
  'user_segment': 'high_value'
});

Step 5: Server-Side Event Tracking

For events that happen outside the browser (subscription renewals, webhook events, backend processes):

import requests

HEAP_APP_ID = "YOUR_APP_ID"
HEAP_SERVER_API = "https://heapanalytics.com/api/track"

def track_server_event(identity, event_name, properties=None):
    """Send a server-side event to Heap."""
    payload = {
        "app_id": HEAP_APP_ID,
        "identity": identity,       # Must match the value used in heap.identify()
        "event": event_name,
        "properties": properties or {},
        "timestamp": None           # None = current time; or ISO 8601 string for historical
    }

    response = requests.post(HEAP_SERVER_API, json=payload)
    return response.status_code == 200

# Example: Track subscription renewal from Stripe webhook
def handle_stripe_renewal(subscription):
    track_server_event(
        identity=subscription['metadata']['heap_user_id'],
        event_name='Subscription Renewed',
        properties={
            'plan_type': subscription['plan']['id'],
            'revenue': subscription['plan']['amount'] / 100,
            'billing_period': subscription['plan']['interval'],
            'renewal_count': int(subscription['metadata'].get('renewal_count', 1))
        }
    )

# Example: Set user properties from server
def update_user_properties(identity, properties):
    payload = {
        "app_id": HEAP_APP_ID,
        "identity": identity,
        "properties": properties
    }
    requests.post("https://heapanalytics.com/api/add_user_properties", json=payload)

update_user_properties('USR-12345', {
    'total_spend': 599.94,
    'lifetime_orders': 6,
    'customer_tier': 'gold'
})

Step 6: Create Definitions in Heap UI

Definitions turn raw autocaptured data into named, reusable events:

  1. In Heap, go to Data > Events & Properties
  2. Click Define New Event
  3. For each business-critical interaction:
    • Name: Descriptive, standardized (e.g., "Signup Button Clicked")
    • Type: Pageview, Click, Submit, or Custom
    • Filters:
      • For clicks: Target text, CSS selector, or hierarchy
      • For pageviews: URL path contains/matches
      • For submits: Form ID or CSS selector
    • Description: Business context and owner

Recommended Definitions:

Definition Type Filter
Pricing Page Viewed Pageview URL path contains /pricing
Signup CTA Clicked Click Button text = "Start Free Trial"
Demo Request Submitted Submit Form ID = demo-request
Product Added to Cart Click CSS selector .add-to-cart-btn
Checkout Completed Custom Event event = "Purchase Completed"

Step 7: Configure Session Replay (Optional)

If using Heap's Session Replay feature:

  1. Go to Settings > Session Replay
  2. Configure privacy settings:
    • Mask all inputs: Enable (prevents capturing typed text)
    • Block specific selectors: Add selectors for sensitive sections
    • Exclude pages: Block recording on sensitive pages (e.g., /account/billing)
  3. Set sampling rate:
    • 100%: All sessions recorded (high storage cost)
    • 10-25%: Good balance of coverage and cost
    • 1-5%: For high-traffic sites to control costs

Verification and QA

Heap Event Visualizer

  1. In Heap, click the Event Visualizer bookmarklet (or browser extension)
  2. Navigate to your website
  3. The visualizer highlights capturable elements on the page
  4. Click any element to see what Heap is capturing:
    • Event type (click, pageview, etc.)
    • Element properties (text, CSS class, hierarchy)
    • Whether the element is suppressed by heap-ignore

Live View

  1. In Heap, go to Users > search for your test user
  2. Click the user to see their event stream
  3. Verify:
    • Autocaptured events appear for all interactions
    • Custom tracked events appear with correct properties
    • Identity merge worked correctly (anonymous + identified events)
    • No PII appears in event properties

Data Audit

Run these checks after initial deployment:

  1. PII scan: Search event properties for patterns matching emails, phone numbers, SSNs
  2. Noise assessment: Check for high-volume events that add no analytical value (decorative animations, tooltip hovers)
  3. Identity check: Verify no users have impossibly high session counts (indicates identity merge issues)
  4. Definition coverage: Ensure all critical business events have formal Definitions

Common Issues

Issue Cause Fix
PII in autocaptured data Missing heap-ignore class on sensitive elements Add class, then request data deletion from Heap
Identity merge wrong user identify() called before auth confirmation Only call after successful login
Too many unique events Autocapture on dynamic content Use heap-ignore on dynamic/generated content
Server events not appearing Wrong identity value Ensure server identity matches heap.identify() value
Session replay captures PII Input masking not enabled Enable "Mask all inputs" in replay settings
Definitions not matching CSS selector changed after site update Use stable selectors (IDs > classes > text)

Deployment Artifacts

  • App ID per environment: Development and production App IDs
  • PII suppression rules: Elements and URLs blocked from capture
  • Event definitions: Named definitions with selectors and descriptions
  • Identity strategy: When to call identify(), resetIdentity(), and addUserProperties()
  • Server-side API integration: Endpoint, authentication, and event payload format
  • Session replay configuration: Sampling rate, privacy settings, excluded pages
  • Governance rules: Blocked events, property transformations, data retention settings
  • Consent implementation: CMP integration, stopTracking()/startTracking() flow

Linked Runbooks

Change Log and Owners

  • Track who manages Definitions and Governance rules
  • Document PII suppression changes with audit dates
  • Maintain identity strategy updates with rationale
  • Record session replay configuration changes
  • Review quarterly: autocapture noise levels, PII compliance, definition accuracy