Amplitude Setup & Implementation | OpsBlu Docs

Amplitude Setup & Implementation

How to implement Amplitude analytics with SDK installation, event taxonomy design, identity resolution, and data governance.

Amplitude is a product analytics platform built around behavioral event data, cohort analysis, and user journey mapping. Unlike page-view-centric platforms like Google Analytics, Amplitude's value depends entirely on the quality of your event taxonomy and identity resolution. A sloppy implementation with inconsistent event names, missing user properties, and broken identity merges does not just produce bad reports -- it permanently corrupts cohort definitions, funnel analyses, and retention curves that product teams rely on for feature decisions.

Why Proper Implementation Matters

Event Quality Determines Product Insight Quality

Amplitude's core analyses are all event-driven:

  • Funnels: Measure conversion between sequential events. If "Add to Cart" is sometimes spelled "add_to_cart" and sometimes "AddToCart", your funnel has a gap.
  • Retention: Tracks whether users return to perform specific events. Inconsistent event names create phantom user drop-off.
  • Cohorts: Groups of users defined by behavior. A missing user property on 30% of events means 30% of users are excluded from targeting cohorts.
  • Pathfinder: Maps user journeys through event sequences. Duplicate or missing events create false paths.

Identity Resolution is Permanent

Amplitude's identity system has strict rules:

  • device_id is automatically assigned per device/browser
  • user_id is your application's login identifier
  • Once a user_id is associated with a device_id, the merge is permanent
  • Calling identify() with the wrong user at the wrong time (e.g., on a shared computer) permanently associates all anonymous events with the wrong user
  • There is no way to un-merge users in Amplitude without contacting support and losing data

Event Volume = Cost

Amplitude pricing is based on event volume (Monthly Tracked Users or event count):

  • Every track() call costs money
  • Autocaptured events (page views, sessions) count toward your quota
  • Server-side events count toward your quota
  • Testing events in production count toward your quota

A poorly configured implementation that fires excessive events can burn through your event quota quickly.

Pre-Implementation Planning

Access and Permissions

Amplitude Organization:

  1. Sign in at analytics.amplitude.com
  2. Verify your organization and project
  3. Request Admin access for implementation work

Required Access:

Platform Role Purpose
Amplitude Admin Project settings, API keys, Govern rules
Amplitude Manager Event management, cohort creation
Your application Developer SDK integration, data layer
Server environment Developer HTTP API integration for backend events

API Keys (per environment):

Environment Key Type Where to Find
Development API Key Settings > Projects > Dev Project > API Key
Staging API Key Settings > Projects > Staging Project > API Key
Production API Key Settings > Projects > Prod Project > API Key
Server-side Secret Key Settings > Projects > API Key (Secret Key tab)

Data Residency:

  • US data center: Default (api.amplitude.com)
  • EU data center: Must be selected at project creation (api.eu.amplitude.com)
  • Cannot be changed after project creation
  • EU residency is required for GDPR compliance for EU-based companies

Event Taxonomy Design

Design your taxonomy before writing any code. Use a tracking plan spreadsheet:

Event Name Category Description Properties Required Type
Page Viewed Navigation User views any page page_name, page_url, referrer Yes string
Button Clicked Interaction User clicks a CTA button_name, button_location Yes string
Signup Started Onboarding User begins registration signup_method Yes string
Signup Completed Onboarding User completes registration signup_method, plan_type Yes string
Feature Used Product User engages a feature feature_name, feature_context Yes string
Purchase Completed Commerce User completes purchase revenue, currency, product_id, plan_type Yes number/string
Subscription Started Commerce User starts subscription plan_type, billing_period, revenue Yes string/number

Naming Conventions:

  • Use Title Case for event names: "Page Viewed", "Signup Completed"
  • Use snake_case for property names: page_name, plan_type
  • Prefix platform-specific events: "iOS: App Opened", "Web: Page Viewed"
  • Never use abbreviations in event names

Identity Strategy

Define when and how to identify users:

Anonymous Visit (device_id only)
  └─> Page Viewed, Button Clicked (anonymous events)
  └─> Signup Started
      └─> setUserId('USER-123')  ← Identity merge happens here
          └─> Signup Completed, Feature Used (identified events)
          └─> All previous anonymous events retroactively attributed

Rules:

  • Set user_id only after confirmed authentication (not on form input, not on email entry)
  • Never set user_id to an email address (use internal user ID)
  • Clear user_id on logout: amplitude.reset() to generate a new device_id
  • For shared devices (kiosks, shared computers): Always call reset() between users

Implementation Walkthrough

Step 1: Install Amplitude Browser SDK

npm Installation (recommended for SPAs):

npm install @amplitude/analytics-browser
import * as amplitude from '@amplitude/analytics-browser';

// Initialize with configuration
amplitude.init('YOUR_API_KEY', {
  // Recommended settings
  defaultTracking: {
    sessions: true,           // Track session start/end
    pageViews: true,          // Track page views automatically
    formInteractions: false,  // Disable unless you need form analytics
    fileDownloads: false      // Disable unless you need download tracking
  },
  minIdLength: 1,             // Minimum user_id length
  flushIntervalMillis: 1000,  // Send events every 1 second
  flushQueueSize: 30,         // Or when 30 events are queued
  logLevel: amplitude.Types.LogLevel.Warn  // Set to Debug during development
});

Script Tag Installation (for traditional sites):

<script type="text/javascript">
  !function(){"use strict";!function(e,t){var r=e.amplitude||{_q:[],_iq:{}};if(r.invoked)
  e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{
  var n=function(e,t){e.prototype[t]=function(){return this._q.push({name:t,
  args:Array.prototype.slice.call(arguments,0)}),this}},s=function(e,t,r){return function(n){
  e._q.push({name:t,args:Array.prototype.slice.call(arguments,0),resolve:r})}},
  o=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove",
  "getUserProperties"];/* truncated for brevity - use full snippet from Amplitude docs */
  r.invoked=!0;var a=t.createElement("script");a.type="text/javascript",a.integrity=
  "sha384-AMPLITUDE_HASH",a.crossOrigin="anonymous",a.async=!0,
  a.src="https://cdn.amplitude.com/libs/analytics-browser-2.x.min.js",
  a.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};
  var c=t.getElementsByTagName("script")[0];c.parentNode.insertBefore(a,c)}}(window,document)}();

  amplitude.init('YOUR_API_KEY', {
    defaultTracking: { sessions: true, pageViews: true }
  });
</script>

Step 2: Implement User Identity

// After successful login
function onUserLogin(user) {
  // Set the user ID (permanent merge with device_id)
  amplitude.setUserId(user.id);  // e.g., 'USR-12345'

  // Set user properties
  const identifyEvent = new amplitude.Identify();
  identifyEvent.set('email_domain', user.email.split('@')[1]);
  identifyEvent.set('plan_type', user.plan);           // 'free', 'pro', 'enterprise'
  identifyEvent.set('account_created', user.createdAt); // ISO date string
  identifyEvent.set('company_name', user.company);
  identifyEvent.setOnce('first_login_date', new Date().toISOString());
  identifyEvent.append('login_methods', user.authMethod); // 'google', 'email', 'sso'

  amplitude.identify(identifyEvent);
}

// On logout
function onUserLogout() {
  amplitude.track('Logged Out');
  amplitude.reset();  // Clears user_id and generates new device_id
}

Step 3: Track Events with Properties

// Page view with context
amplitude.track('Page Viewed', {
  page_name: document.title,
  page_url: window.location.href,
  page_path: window.location.pathname,
  referrer: document.referrer,
  page_category: getPageCategory()  // 'product', 'blog', 'pricing', etc.
});

// Feature usage
amplitude.track('Feature Used', {
  feature_name: 'Export Dashboard',
  feature_context: 'analytics_page',
  export_format: 'csv',
  row_count: 1500
});

// Purchase with revenue
amplitude.track('Purchase Completed', {
  revenue: 99.00,
  currency: 'USD',
  product_id: 'PRO_ANNUAL',
  plan_type: 'pro',
  billing_period: 'annual',
  discount_applied: true,
  discount_code: 'SAVE20'
});

// Or use the Revenue class for Amplitude's built-in revenue tracking
const revenue = new amplitude.Revenue();
revenue.setProductId('PRO_ANNUAL');
revenue.setPrice(99.00);
revenue.setQuantity(1);
revenue.setRevenueType('subscription');
revenue.setEventProperties({
  plan_type: 'pro',
  billing_period: 'annual'
});
amplitude.revenue(revenue);

Step 4: Implement Server-Side Tracking

For backend events that cannot be captured client-side (subscription renewals, webhook events, backend processes):

const https = require('https');

const AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY;
const AMPLITUDE_ENDPOINT = 'https://api2.amplitude.com/2/httpapi';
// For EU: 'https://api.eu.amplitude.com/2/httpapi'

async function trackServerEvent(userId, eventName, eventProperties) {
  const payload = {
    api_key: AMPLITUDE_API_KEY,
    events: [{
      user_id: userId,
      event_type: eventName,
      event_properties: eventProperties,
      time: Date.now(),
      platform: 'server',
      ip: '$remote'  // Let Amplitude resolve from request IP
    }]
  };

  const response = await fetch(AMPLITUDE_ENDPOINT, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  });

  return response.json();
}

// Example: Track subscription renewal from Stripe webhook
async function handleStripeRenewal(subscription) {
  await trackServerEvent(subscription.metadata.amplitude_user_id, 'Subscription Renewed', {
    plan_type: subscription.plan.id,
    revenue: subscription.plan.amount / 100,
    currency: subscription.currency.toUpperCase(),
    billing_period: subscription.plan.interval,
    renewal_count: subscription.metadata.renewal_count
  });
}

// Example: Track backend process completion
async function handleReportGenerated(userId, reportId) {
  await trackServerEvent(userId, 'Report Generated', {
    report_id: reportId,
    report_type: 'monthly_analytics',
    generation_time_ms: 3400
  });
}

Step 5: Configure Amplitude Govern

Govern enforces your taxonomy by blocking or transforming non-conforming events:

  1. In Amplitude, go to Data > Events

  2. For each expected event:

    • Click the event name
    • Set Status to "Expected" (planned) or "Live" (in production)
    • Add a Description explaining what the event represents
    • Mark required properties
    • Set property types (string, number, boolean)
  3. Configure Blocking Rules:

    • Go to Data > Govern > Block/Filter
    • Block events with unexpected names (catches typos)
    • Block events with invalid property types
    • Drop sensitive properties (email, phone, SSN) before storage
  4. Configure Transformations:

    • Merge duplicate event names (e.g., "add_to_cart" -> "Add to Cart")
    • Rename properties for consistency
    • Apply across all incoming data

Step 6: Set Up Group Analytics (Optional)

For B2B products where you need account-level analytics:

// Set the user's group (company/account)
amplitude.setGroup('company', 'ACME Corp');

// Set group properties
const groupIdentify = new amplitude.Identify();
groupIdentify.set('plan', 'enterprise');
groupIdentify.set('employee_count', 500);
groupIdentify.set('industry', 'technology');
amplitude.groupIdentify('company', 'ACME Corp', groupIdentify);

This enables account-level funnels, retention, and revenue analysis in Amplitude.

Verification and QA

Event Stream (Real-Time Debugging)

  1. In Amplitude, go to User Lookup
  2. Search by your test user ID or device ID
  3. View the Event Stream to see events in real-time
  4. For each event, verify:
    • Event name matches taxonomy exactly (case-sensitive)
    • All required properties are present
    • Property values have correct types
    • user_id and device_id are correct

Instrumentation Alerts

  1. Go to Data > Events
  2. Check for:
    • Unexpected events: Events not in your taxonomy (typos, test events)
    • Volume anomalies: Sudden spikes or drops in event counts
    • Property issues: Missing required properties or wrong types

Identity Validation

  1. Create a test user account
  2. Browse anonymously, then log in
  3. In User Lookup, verify:
    • Anonymous events are merged with the identified user
    • device_id and user_id are both present after login
    • User properties are correctly set
  4. Log out and verify reset() generates a new device_id
  5. Log in as a different user and verify no cross-contamination

Common Issues

Issue Cause Fix
Events not appearing Wrong API key or network block Check API key, test with logLevel: Debug
Duplicate events SDK initialized twice Ensure init() is called only once
Identity merge wrong setUserId called before auth confirmation Only set after successful login
Missing properties Property passed as undefined Check for null/undefined before tracking
EU compliance failure Using US endpoint for EU project Verify data center in project settings
Event quota exceeded Autocapture or excessive tracking Disable unnecessary defaultTracking options
Properties show wrong type String passed instead of number Validate types before track() call

Deployment Artifacts

  • Tracking plan: Event names, properties, types, and descriptions (sync with Govern)
  • API keys and secrets: Per environment, stored securely
  • Identity strategy document: When to set/clear user_id, merge rules, shared device handling
  • SDK configuration: init() parameters per environment
  • Server-side integration: HTTP API endpoint, authentication, and payload format
  • Govern rules: Blocking rules, transformations, and expected event statuses
  • Data residency: US or EU endpoint configuration

Linked Runbooks

Change Log and Owners

  • Document who owns Govern approvals and taxonomy changes
  • Track open questions about default tracking settings and their quota impact
  • Maintain API key rotation schedule
  • Record identity strategy changes with rationale
  • Review quarterly: event volume trends, Govern violations, data quality metrics