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:
- Event Type: The action name (e.g., "Song Played", "Purchase Complete")
- Event Properties: Context about the event (e.g.,
{"song_name": "Thriller", "genre": "Pop"}) - User Properties: Attributes describing the user (e.g.,
{"plan": "Premium", "signup_date": "2024-01-01"}) - User ID: Unique identifier (or Device ID for anonymous users)
- 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.
Recommended Event Taxonomy
App Lifecycle:
App Opened: User opens the appApp Backgrounded: User backgrounds the appApp Updated: User updates to new version
User Lifecycle:
Sign Up: Account creationLogin: User authenticationLogout: User logs out
Content & Navigation:
Screen Viewed: User views a screen/pageContent Viewed: User views specific contentSearch: User performs searchButton Clicked: User clicks CTA/button
Engagement:
Share: User shares contentRating Submitted: User rates contentComment 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
// 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 setadd: Increment/decrement numeric valueappend: Add to arrayprepend: Add to beginning of arrayunset: Remove propertypreInsert: Add unique value to arraypostInsert: Add unique value to end of arrayremove: 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:
- Go to User & Activity > User Lookup
- Enter User ID or Device ID
- View complete event stream for that user
- Inspect event and user properties
3. Event Stream (Live)
Real-time event monitoring:
- Navigate to User & Activity > Events
- Filter by event type
- See events as they arrive (within seconds)
- Click event to see full payload
4. Instrumentation Explorer
Validate implementation:
- Go to Data > Sources
- Select your source
- View Instrumentation Explorer
- See all event types and properties
- 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.comorapi2.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, neverproductIdorProductID - Use appropriate types: numbers for metrics, booleans for flags
- Document property definitions
- Include units in names:
duration_seconds, notduration - 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: