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:
- Sign in at
heapanalytics.com - Verify your Heap environment (each environment has a separate App ID)
- 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:
- Create a Custom HTML tag
- Paste the Heap snippet code
- Set trigger: All Pages (with consent condition if required)
- 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:
- In Heap, go to Data > Events & Properties
- Click Define New Event
- 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:
- Go to Settings > Session Replay
- 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)
- 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
- In Heap, click the Event Visualizer bookmarklet (or browser extension)
- Navigate to your website
- The visualizer highlights capturable elements on the page
- 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
- In Heap, go to Users > search for your test user
- Click the user to see their event stream
- 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:
- PII scan: Search event properties for patterns matching emails, phone numbers, SSNs
- Noise assessment: Check for high-volume events that add no analytical value (decorative animations, tooltip hovers)
- Identity check: Verify no users have impossibly high session counts (indicates identity merge issues)
- 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(), andaddUserProperties() - 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
- Install or Embed the Tag or SDK -- Heap snippet deployment
- Event Tracking -- Custom event tracking and definition management
- Data Layer Setup -- Data layer integration for custom properties
- Cross-Domain Tracking -- Identity management across domains
- Server-Side vs Client-Side -- Server API vs. autocapture decisions
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