Amplitude Event Tracking | Blue Frog Docs

Amplitude Event Tracking

Complete guide to Amplitude event tracking and measurement

Amplitude Event Tracking

Overview

Amplitude is a product analytics platform built for understanding user behavior through events. Like Mixpanel, Amplitude treats every interaction as a discrete event, but it emphasizes behavioral cohorts, retention analysis, and product experimentation. The platform is designed to help product teams answer questions like "Which features drive retention?" and "How do users move through our product?"

Amplitude's strength lies in its ability to connect individual user actions into cohesive behavioral patterns, making it particularly powerful for SaaS products, mobile apps, and digital products where engagement and retention are critical metrics.

Event Model

How Amplitude Events Work

Every event in Amplitude consists of:

  1. Event Type: The action name (e.g., "Song Played", "Purchase Complete")
  2. Event Properties: Context about the event (e.g., {"song_name": "Thriller", "genre": "Pop"})
  3. User Properties: Attributes describing the user (e.g., {"plan": "Premium", "signup_date": "2024-01-01"})
  4. User ID: Unique identifier (or Device ID for anonymous users)
  5. Timestamp: When the event occurred

Event Structure:

{
  "event_type": "Song Played",
  "user_id": "user_12345",
  "device_id": "device_abc123",
  "time": 1640995200000,
  "event_properties": {
    "song_name": "Thriller",
    "artist": "Michael Jackson",
    "duration_seconds": 358,
    "source": "playlist"
  },
  "user_properties": {
    "plan": "Premium",
    "country": "US"
  }
}

Key Concepts

  • Event Type: What happened
  • Event Properties: Details about what happened
  • User Properties: Who the user is
  • User ID: Persistent identifier across devices
  • Device ID: Anonymous identifier before login
  • Groups: Organization-level properties (companies, teams)

Limits

  • Event type name: 1024 characters (recommend under 50)
  • Property name: 1024 characters (recommend under 50)
  • Property value: 1024 characters for strings
  • Properties per event: 1000 properties (recommend under 50)
  • User properties: 1000 per user

Standard Events

Amplitude doesn't enforce predefined events, but recommends a taxonomy for common use cases.

App Lifecycle:

  • App Opened: User opens the app
  • App Backgrounded: User backgrounds the app
  • App Updated: User updates to new version

User Lifecycle:

  • Sign Up: Account creation
  • Login: User authentication
  • Logout: User logs out

Content & Navigation:

  • Screen Viewed: User views a screen/page
  • Content Viewed: User views specific content
  • Search: User performs search
  • Button Clicked: User clicks CTA/button

Engagement:

  • Share: User shares content
  • Rating Submitted: User rates content
  • Comment Posted: User comments

Implementation Examples

// App lifecycle
amplitude.track('App Opened', {
  'source': 'push_notification',
  'app_version': '2.1.0'
});

// User authentication
amplitude.track('Sign Up', {
  'method': 'email',
  'referral_source': 'google_ad',
  'plan_selected': 'trial'
});

// Content engagement
amplitude.track('Screen Viewed', {
  'screen_name': 'Product Details',
  'product_id': 'SKU_12345',
  'category': 'Electronics'
});

Custom Events

Custom events let you track product-specific interactions that matter to your business.

Creating Custom Events

JavaScript SDK:

// Basic event
amplitude.track('Feature Used');

// Event with properties
amplitude.track('Video Watched', {
  'video_id': 'vid_12345',
  'video_title': 'Onboarding Tutorial',
  'video_length_seconds': 180,
  'completion_percent': 85,
  'quality': '1080p',
  'platform': 'web'
});

// Event with user properties
amplitude.track('Subscription Upgraded', {
  'old_plan': 'Basic',
  'new_plan': 'Pro',
  'price_difference': 20.00,
  'upgrade_trigger': 'paywall'
});

Python SDK:

from amplitude import Amplitude

client = Amplitude('API_KEY')

# Track event
event = {
    'user_id': 'user_12345',
    'event_type': 'Purchase Completed',
    'event_properties': {
        'product_id': 'SKU_789',
        'price': 49.99,
        'currency': 'USD',
        'quantity': 2
    },
    'user_properties': {
        'total_purchases': 5,
        'lifetime_value': 249.95
    }
}

client.track(event)

Mobile (iOS - Swift):

import Amplitude

// Track event
Amplitude.instance().logEvent("Level Completed", withEventProperties: [
    "level_name": "Desert Storm",
    "level_number": 8,
    "score": 9500,
    "time_seconds": 145,
    "stars_earned": 3
])

// Set user property
Amplitude.instance().setUserProperties([
    "total_levels_completed": 8,
    "favorite_game_mode": "adventure"
])

Mobile (Android - Kotlin):

val amplitude = Amplitude.getInstance()

// Track event
val eventProps = JSONObject()
eventProps.put("level_name", "Desert Storm")
eventProps.put("level_number", 8)
eventProps.put("score", 9500)

amplitude.logEvent("Level Completed", eventProps)

Event Naming Best Practices

✅ Good:

  • Use object + action: "Song Played", "Article Read"
  • Be specific but not granular: "Video Played" not "Video_Played_From_Homepage_At_10AM"
  • Use Title Case with spaces
  • Be consistent across your taxonomy

❌ Avoid:

  • Generic names: "Event", "Action"
  • Technical names: "onClick_handler_243"
  • PascalCase or snake_case: use Title Case
  • Including variable data: "Video_vid123_Played"

Ecommerce Events

Amplitude supports comprehensive ecommerce tracking through custom events.

Product Discovery

// Product List Viewed
amplitude.track('Product List Viewed', {
  'category': 'Electronics',
  'list_type': 'search_results',
  'product_count': 24,
  'sort_order': 'price_low_to_high',
  'filters': ['in_stock', 'free_shipping']
});

// Product Viewed
amplitude.track('Product Viewed', {
  'product_id': 'SKU_12345',
  'product_name': 'Wireless Mouse',
  'price': 29.99,
  'currency': 'USD',
  'category': 'Electronics > Accessories',
  'brand': 'LogiTech',
  'in_stock': true,
  'images_count': 5
});

Cart Management

// Product Added to Cart
amplitude.track('Product Added', {
  'product_id': 'SKU_12345',
  'product_name': 'Wireless Mouse',
  'price': 29.99,
  'quantity': 1,
  'cart_total': 29.99,
  'cart_items': 1,
  'source': 'product_page'
});

// Product Removed from Cart
amplitude.track('Product Removed', {
  'product_id': 'SKU_12345',
  'removal_reason': 'out_of_stock',
  'cart_total': 0,
  'cart_items': 0
});

// Cart Viewed
amplitude.track('Cart Viewed', {
  'cart_total': 89.97,
  'cart_items': 3,
  'product_ids': ['SKU_12345', 'SKU_67890', 'SKU_11111']
});

Checkout Process

// Checkout Started
amplitude.track('Checkout Started', {
  'cart_total': 89.97,
  'cart_items': 3,
  'checkout_step': 1,
  'checkout_type': 'standard'
});

// Checkout Step Completed
amplitude.track('Checkout Step Completed', {
  'checkout_step': 2,
  'step_name': 'Shipping Information',
  'shipping_method': 'standard',
  'estimated_delivery_days': 5
});

// Payment Info Entered
amplitude.track('Payment Info Entered', {
  'payment_method': 'credit_card',
  'card_type': 'visa',
  'save_payment_info': true
});

// Order Completed
amplitude.track('Order Completed', {
  'order_id': 'ORDER_12345',
  'revenue': 89.97,
  'tax': 7.20,
  'shipping': 10.00,
  'total': 107.17,
  'currency': 'USD',
  'item_count': 3,
  'payment_method': 'credit_card',
  'shipping_method': 'standard',
  'coupon_code': 'SAVE10',
  'discount_amount': 9.00,
  'is_first_purchase': false,
  'products': [
    {
      'product_id': 'SKU_12345',
      'quantity': 2,
      'price': 29.99
    }
  ]
});

// Log revenue (for Revenue Analysis)
amplitude.setRevenue({
  'revenue': 107.17,
  'productId': 'ORDER_12345',
  'quantity': 3,
  'revenueType': 'purchase'
});

Subscription Tracking

// Trial Started
amplitude.track('Trial Started', {
  'plan_name': 'Pro Plan',
  'trial_length_days': 14,
  'trial_price': 0,
  'full_price': 29.99,
  'billing_cycle': 'monthly'
});

// Subscription Started
amplitude.track('Subscription Started', {
  'plan_name': 'Pro Annual',
  'plan_price': 299.99,
  'billing_cycle': 'yearly',
  'payment_method': 'credit_card',
  'from_trial': true
});

// Subscription Renewed
amplitude.track('Subscription Renewed', {
  'plan_name': 'Pro Monthly',
  'renewal_count': 6,
  'next_billing_date': '2024-07-01'
});

// Subscription Cancelled
amplitude.track('Subscription Cancelled', {
  'plan_name': 'Pro Monthly',
  'cancellation_reason': 'too_expensive',
  'months_active': 6,
  'total_revenue': 179.94,
  'downgrade_offered': true,
  'feedback_provided': true
});

User Properties

User properties describe attributes of the user, not their actions.

Setting User Properties

JavaScript:

// Identify user
amplitude.setUserId('user_12345');

// Set properties
amplitude.setUserProperties({
  'name': 'John Doe',
  'email': 'john@example.com',
  'plan': 'Pro',
  'signup_date': '2024-01-15',
  'account_age_days': 45,
  'total_purchases': 3
});

// Set once (never overwrites)
amplitude.setOnceUserProperties({
  'initial_referrer': document.referrer,
  'first_visit_date': new Date().toISOString()
});

// Increment numeric property
amplitude.identify(new amplitude.Identify()
  .add('credits_balance', 100)
  .add('login_count', 1)
);

// Set property
amplitude.identify(new amplitude.Identify()
  .set('subscription_tier', 'Premium')
);

// Append to array
amplitude.identify(new amplitude.Identify()
  .append('purchase_history', 'ORDER_123')
);

// Prepend to array
amplitude.identify(new amplitude.Identify()
  .prepend('recent_searches', 'wireless mouse')
);

Python:

from amplitude import Amplitude

client = Amplitude('API_KEY')

# Set user properties
event = {
    'user_id': 'user_12345',
    'user_properties': {
        'name': 'John Doe',
        'email': 'john@example.com',
        'plan': 'Pro',
        'total_logins': 42
    }
}

client.track(event)

# Increment
event = {
    'user_id': 'user_12345',
    'user_properties': {
        '$add': {
            'credits': 100
        }
    }
}

client.track(event)

User Property Operations

Amplitude supports multiple operations:

  • set: Set value (overwrites)
  • setOnce: Set only if not already set
  • add: Increment/decrement numeric value
  • append: Add to array
  • prepend: Add to beginning of array
  • unset: Remove property
  • preInsert: Add unique value to array
  • postInsert: Add unique value to end of array
  • remove: Remove value from array
const identify = new amplitude.Identify()
  .set('plan', 'Pro')
  .setOnce('first_login', new Date())
  .add('login_count', 1)
  .append('devices', 'iPhone 14')
  .unset('temporary_flag');

amplitude.identify(identify);

Event Properties

Event properties provide context specific to an individual event.

Default Properties

Amplitude automatically captures:

  • Platform/OS: platform, os_name, os_version
  • Device: device_type, device_manufacturer, device_model
  • Location: city, region, country, dma, language
  • App/Web: app_version, carrier, library
  • Session: session_id, event_id
  • Network: ip_address (hashed by default)

Custom Event Properties

// Rich event properties
amplitude.track('Article Read', {
  'article_id': 'blog_456',
  'article_title': 'Introduction to Product Analytics',
  'author': 'Jane Smith',
  'category': 'Education',
  'word_count': 2500,
  'reading_time_seconds': 420,
  'scroll_depth_percent': 90,
  'images_count': 5,
  'video_embeds': 2,
  'related_articles_shown': 3,
  'published_date': '2024-01-20',
  'is_premium': false,
  'tags': ['analytics', 'product', 'tutorial']
});

Property Data Types

  • String: "Premium User"
  • Number: 29.99, 42
  • Boolean: true, false
  • Array: ["tag1", "tag2", "tag3"]
  • Object: {"key": "value"} (limited, prefer flat structure)

Super Properties

Properties sent with every event:

// Set super properties
amplitude.getInstance().setUserProperties({
  'app_version': '2.1.0',
  'environment': 'production'
});

// These will be included in all subsequent events
amplitude.track('Button Clicked'); // Includes app_version and environment

Implementation Methods

1. JavaScript SDK (Web)

Installation via CDN:

<script type="text/javascript">
!function(){"use strict";!function(e,t){var n=e.amplitude||{_q:[],_iq:{}};if(n.invoked)e.console&&console.error&&console.error("Amplitude snippet has been loaded.");else{n.invoked=!0;var r=t.createElement("script");r.type="text/javascript",r.integrity="sha384-[INTEGRITY_HASH]",r.crossOrigin="anonymous",r.async=!0,r.src="https://cdn.amplitude.com/libs/analytics-browser-2.0.0-min.js.gz",r.onload=function(){e.amplitude.runQueuedFunctions||console.log("[Amplitude] Error: could not load SDK")};var s=t.getElementsByTagName("script")[0];s.parentNode.insertBefore(r,s);for(var o=function(){return this._q=[],this},i=["add","append","clearAll","prepend","set","setOnce","unset","preInsert","postInsert","remove","getUserProperties"],a=0;a<i.length;a++)o.prototype[i[a]]=function(e){return function(){return this._q.push({name:e,args:Array.prototype.slice.call(arguments,0)}),this}}(i[a]);n.Identify=o;for(var u=function(){this._q=[]},c=["getEventProperties","setProductId","setQuantity","setPrice","setRevenue","setRevenueType","setEventProperties"],p=0;p<c.length;p++)u.prototype[c[p]]=function(e){return function(){return this._q.push([e].concat(Array.prototype.slice.call(arguments,0))),this}}(c[p]);n.Revenue=u;var d=["getDeviceId","setDeviceId","getSessionId","setSessionId","getUserId","setUserId","setOptOut","setTransport","reset"],l=["init","add","remove","track","logEvent","identify","Identify","setGroup","revenue","Revenue"];function v(e){function t(t){e[t]=function(){var n={promise:new Promise((n=>{e._q.push({name:t,args:Array.prototype.slice.call(arguments,0),resolve:n})}))};return isFinite(arguments[arguments.length-1])?n:n.promise}}for(var n=0;n<l.length;n++)t(l[n])}v(n),n.createInstance=function(e){return n._iq[e]={_q:[]},v(n._iq[e]),n._iq[e]},e.amplitude=n}}(window,document)}();

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

Installation via NPM:

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

amplitude.init('YOUR_API_KEY', 'user_12345', {
  defaultTracking: {
    sessions: true,
    pageViews: true,
    formInteractions: true,
    fileDownloads: true
  }
});

// Track event
amplitude.track('Button Clicked', {
  'button_name': 'signup_cta'
});

2. Server-Side SDKs

Node.js:

const { Amplitude } = require('@amplitude/analytics-node');

const client = new Amplitude('YOUR_API_KEY');

// Track event
client.logEvent({
  event_type: 'API Request',
  user_id: 'user_12345',
  event_properties: {
    endpoint: '/api/users',
    method: 'GET',
    response_time_ms: 45
  }
});

// Flush events
await client.flush();

Python:

from amplitude import Amplitude

client = Amplitude('YOUR_API_KEY')

# Track event
event = {
    'user_id': 'user_12345',
    'event_type': 'Background Job Completed',
    'event_properties': {
        'job_type': 'data_export',
        'duration_seconds': 120,
        'records_processed': 10000
    }
}

client.track(event)

Java:

import com.amplitude.Amplitude;
import com.amplitude.Event;

Amplitude client = Amplitude.getInstance();
client.init("YOUR_API_KEY");

Event event = new Event("Purchase Completed", "user_12345");
event.eventProperties.put("product_id", "SKU_789");
event.eventProperties.put("price", 49.99);

client.logEvent(event);

3. Mobile SDKs

iOS (Swift):

import Amplitude

// Initialize
Amplitude.instance().trackingSessionEvents = true
Amplitude.instance().initializeApiKey("YOUR_API_KEY")

// Set user ID
Amplitude.instance().setUserId("user_12345")

// Track event
Amplitude.instance().logEvent("Screen Viewed", withEventProperties: [
    "screen_name": "Home",
    "previous_screen": "Onboarding"
])

// Identify user
let identify = AMPIdentify()
    .set("plan", value: "Pro" as NSString)
    .add("login_count", value: 1 as NSNumber)

Amplitude.instance().identify(identify)

Android (Kotlin):

import com.amplitude.api.Amplitude
import org.json.JSONObject

// Initialize
val amplitude = Amplitude.getInstance()
    .initialize(this, "YOUR_API_KEY")
    .enableForegroundTracking(application)

// Set user ID
amplitude.userId = "user_12345"

// Track event
val properties = JSONObject()
properties.put("screen_name", "Home")
properties.put("previous_screen", "Onboarding")

amplitude.logEvent("Screen Viewed", properties)

// Identify
val identify = Identify()
    .set("plan", "Pro")
    .add("login_count", 1)

amplitude.identify(identify)

4. HTTP API

curl --location --request POST 'https://api2.amplitude.com/2/httpapi' \
--header 'Content-Type: application/json' \
--data-raw '{
  "api_key": "YOUR_API_KEY",
  "events": [{
    "user_id": "user_12345",
    "event_type": "Song Played",
    "time": 1640995200000,
    "event_properties": {
      "song_name": "Thriller",
      "artist": "Michael Jackson"
    }
  }]
}'

Debugging & Validation

1. Debug Mode

Enable debug logging:

// JavaScript
amplitude.init('YOUR_API_KEY', {
  logLevel: amplitude.Types.LogLevel.Debug
});

// iOS
Amplitude.instance().setLogLevel(AMPLogLevel.DEBUG)

// Android
Amplitude.getInstance().setLogLevel(Log.DEBUG)

2. User Lookup

In Amplitude dashboard:

  1. Go to User & Activity > User Lookup
  2. Enter User ID or Device ID
  3. View complete event stream for that user
  4. Inspect event and user properties

3. Event Stream (Live)

Real-time event monitoring:

  1. Navigate to User & Activity > Events
  2. Filter by event type
  3. See events as they arrive (within seconds)
  4. Click event to see full payload

4. Instrumentation Explorer

Validate implementation:

  1. Go to Data > Sources
  2. Select your source
  3. View Instrumentation Explorer
  4. See all event types and properties
  5. Identify missing or incorrect data

5. Browser DevTools

Console Logging:

amplitude.track('Test Event', { test: true });
// Check console for "[Amplitude] Event uploaded: Test Event"

Network Tab:

  • Filter for api.amplitude.com or api2.amplitude.com
  • Inspect request payload
  • Verify API key and event data

6. Data Validation

// Check user ID
console.log(amplitude.getUserId());

// Check device ID
console.log(amplitude.getDeviceId());

// Check session ID
console.log(amplitude.getSessionId());

Best Practices

Event Design

✅ Do:

  • Use object + action format: "Video Played", "Article Shared"
  • Be descriptive: "Checkout Completed" not "Done"
  • Use Title Case with spaces
  • Track both success and failure states
  • Include relevant context in properties

❌ Don't:

  • Use vague names: "Event", "Action", "Click"
  • Include dynamic values in event names
  • Create redundant events
  • Track sensitive PII

Property Strategy

✅ Do:

  • Use consistent naming: always product_id, never productId or ProductID
  • Use appropriate types: numbers for metrics, booleans for flags
  • Document property definitions
  • Include units in names: duration_seconds, not duration
  • Use arrays for multi-value properties

❌ Don't:

  • Send empty or null values
  • Exceed recommended limits (50 properties)
  • Nest objects deeply
  • Use inconsistent property names across events

User Identity

Managing Anonymous & Identified Users:

// Anonymous user (automatic device_id)
amplitude.track('Page Viewed');

// User signs up - set user ID
amplitude.setUserId('user_12345');

// Subsequent events tied to user_12345
amplitude.track('Profile Created');

// User logs out - create new device ID
amplitude.reset();

// User logs back in
amplitude.setUserId('user_12345');

Best Practices:

  • Use permanent IDs (database primary keys, not emails)
  • Set user ID immediately after authentication
  • Reset on logout for shared devices
  • Use device ID for anonymous tracking

Groups & Accounts

For B2B SaaS, track company-level data:

// Set user's group
amplitude.setGroup('company', 'acme_corp');

// Set group properties
const groupIdentify = new amplitude.Identify()
  .set('plan', 'Enterprise')
  .set('employee_count', 500)
  .set('industry', 'Technology');

amplitude.groupIdentify('company', 'acme_corp', groupIdentify);

// All events now include company context
amplitude.track('Feature Used', {
  'feature_name': 'advanced_reports'
});

Performance

  • Load SDK asynchronously
  • Batch events (automatic in most SDKs)
  • Use sampling for high-frequency events
  • Avoid tracking on every scroll/mousemove
  • Set appropriate flush intervals

Privacy & Compliance

✅ Do:

// Disable tracking based on consent
if (!userConsented) {
  amplitude.setOptOut(true);
}

// Use privacy flags
amplitude.init('YOUR_API_KEY', {
  disableCookies: true, // For cookie-less tracking
  defaultTracking: false // Disable auto-tracking
});

// Hash PII
amplitude.setUserId(sha256(userEmail));

❌ Don't:

  • Track email, phone, address without hashing
  • Ignore opt-out preferences
  • Assume compliance by default
  • Send credit card, SSN, passwords

Data Quality

  • Use separate projects for dev/staging/production
  • Implement QA checklist before launches
  • Monitor event volume for anomalies
  • Set up data validation rules
  • Regular audits of tracking implementation

Organizational

  • Maintain tracking plan (event taxonomy)
  • Document all events and properties
  • Use consistent naming conventions team-wide
  • Establish governance for new events
  • Regular reviews with stakeholders

Additional Resources:

// SYS.FOOTER