---
name: activity-amplitude
description: >-
Configures Amplitude as the event source for Autoplay using the @amplitude/unified SDK.
Installs the SDK, initializes it with autocapture and session replay, calls
amplitude.setUserId() and amplitude.identify() with product_id on login, creates a
server-side proxy for the identify call so credentials stay server-side, runs the
Autoplay registration script to get ingest/stream URLs, and guides the customer through
creating an Amplitude HTTP Event Streaming destination with the Freemarker template.
Also patches Content-Security-Policy headers if the project uses them.
disable-model-invocation: true
---
# Autoplay ร Amplitude Integration Guide
This guide is structured for an AI agent. Steps marked **๐ค AGENT** are handled autonomously. Steps marked **๐ง HUMAN** require customer input.
---
## Step 1 โ Understand the project
**๐ค AGENT**
Before writing any code, read the project to determine:
- **Frontend framework** โ Next.js, Nuxt, Angular, Vue, SvelteKit, plain React, etc.
- **Auth system** โ what library handles login/logout and how to get the current user and session ID
- **Env var conventions** โ how the project names and exposes environment variables (e.g. `VITE_`, `NEXT_PUBLIC_`, `NG_APP_`, no prefix, etc.)
- **App entry point** โ where to initialize SDKs (e.g. `main.ts`, `app.module.ts`, `_app.tsx`, `main.js`)
- **Package manager** โ npm, yarn, pnpm, bun
Do not write any code until this is understood.
---
## Step 2 โ Install the Amplitude SDK
**๐ค AGENT**
Check if `@amplitude/unified` is already in the project's dependencies. If not, install it:
npm install @amplitude/unified
# or yarn / pnpm / bun equivalent
---
## Step 3 โ Get Amplitude credentials
### ๐ง HUMAN โ Amplitude API Key
Ask the customer to open their Amplitude project and copy the API Key.
Walkthrough: https://app.arcade.software/share/ycesTzu0o9kI2N56wytr
### ๐ง HUMAN โ Amplitude Project ID
Ask the customer to go to Settings โ Projects โ [their project] and copy the numeric Project ID.
Walkthrough: https://app.arcade.software/share/gbMSMIenMpBYhCWbLFrh
---
## Step 4 โ Register with Autoplay
**๐ค AGENT**
python3 -m venv .venv && source .venv/bin/activate
pip install autoplay-sdk
import asyncio
from autoplay_sdk.admin import onboard_product
from autoplay_sdk.providers import AmplitudeProvider
async def main():
result = await onboard_product(
"<AMPLITUDE_PROJECT_ID>",
contact_email="<customer email>",
user_activity_provider=AmplitudeProvider(),
print_operator_summary=True,
)
asyncio.run(main())
The script prints three values needed in Steps 5 and 6:
- amplitude_ingest_url โ Amplitude dashboard HTTP destination URL
- stream_url โ Identify endpoint called from the app
- unkey_key โ Bearer token for both
Add to the project's env file. Client-side values (API Key, Product ID) use the framework's public prefix. The rest stay server-side.
---
## Step 5 โ Wire Amplitude into the app
**๐ค AGENT**
### Initialize at app startup
import * as amplitude from '@amplitude/unified';
amplitude.initAll('<AMPLITUDE_API_KEY>', {
analytics: { autocapture: true },
sessionReplay: { sampleRate: 1 },
});
autocapture: true is required.
### Identify on login
amplitude.setUserId(<user.id>);
const identifyObj = new amplitude.Identify();
identifyObj.set('product_id', '<AUTOPLAY_PRODUCT_ID>');
identifyObj.set('email', <user.email>);
identifyObj.set('name', <user.name>);
amplitude.identify(identifyObj);
const sessionId = amplitude.getSessionId();
if (sessionId) {
fetch('/api/amplitude-identify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: <user.email>,
session_id: String(sessionId),
product_id: '<AUTOPLAY_PRODUCT_ID>',
}),
});
}
### Server-side proxy for the identify call
Create a backend endpoint (Next.js route handler, Express, Nuxt server route, etc.) that forwards:
POST <stream_url>/identify
Content-Type: application/json
{ email, session_id, product_id }
No auth header needed for the identify call.
### Reset on logout
amplitude.reset();
---
## Step 6 โ Create the Amplitude Event Streaming destination
### ๐ง HUMAN
1. Go to Data โ Destinations โ Add Destination โ HTTP โ Event Streaming
2. Endpoint URL: amplitude_ingest_url from Step 4
Authentication: Bearer Token
Token: unkey_key from Step 4
Events to send: All events
3. Paste this Freemarker template in the Event Body section exactly:
<#setting number_format="0.####">
<#assign et = input.event_type!''>
<#assign ep = input.event_properties!{}>
<#assign up = input.user_properties!{}>
{
"events": [{
"event_type": "<#if et?starts_with('Viewed') || et == '[Amplitude] Page Viewed' || et == 'Page Viewed'>$pageview<#elseif et == '[Amplitude] Element Clicked' || et == '[Amplitude] Element Changed' || et?starts_with('Form')>$autocapture<#else>${et}</#if>",
"user_id": "${input.user_id!''}",
"device_id": "${input.device_id!''}",
"session_id": ${input.session_id!0},
"time": ${input.time!0},
"user_properties": { <#list up?keys as k>"${k}": "${up[k]}"<#sep>, </#sep></#list> },
"event_properties": {
"[Amplitude] Page URL": "${ep['Page URL']!ep['[Amplitude] Page URL']!''}",
"[Amplitude] Page Title": "${ep['Page Title']!ep['[Amplitude] Page Title']!''}",
"$event_type": "<#if et == '[Amplitude] Element Changed'>change<#elseif et?starts_with('Form Submitted')>submit<#elseif et?starts_with('Form Started')>focus<#else>click</#if>",
"$current_url": "${ep['Page URL']!ep['[Amplitude] Page URL']!''}",
"$button_text": "${ep['[Amplitude] Element Text']!ep['Element Text']!''}",
"$elements_chain": "${ep['[Amplitude] Element Path']!ep['[Amplitude] Element Hierarchy']!''}",
"$element_id": "${ep['[Amplitude] Element ID']!ep['Element ID']!''}",
"$element_tag": "${ep['[Amplitude] Element Tag']!ep['Element Tag']!''}"
}
}]
}
Walkthrough: https://app.arcade.software/share/NeCcl6dtC7DQdjOjue28
---
## Step 7 โ Verify
**๐ค AGENT**
Ask the customer to log in and navigate around. Then verify:
curl -N "<stream_url>" -H "Authorization: Bearer <unkey_key>"
Session activity should appear within seconds.
---
## Content Security Policy (CSP)
**๐ค AGENT**
If the project sets a Content-Security-Policy header, add:
- connect-src: https://*.amplitude.com
- script-src: https://cdn.amplitude.com
- worker-src: 'self' blob:
---
## Common mistakes
| Problem | Fix |
|---------|-----|
| 401 on destination | Bearer token must be `Bearer <unkey_key>` โ no extra spaces or quotes |
| 404 errors | Project ID in URL must match registration |
| Missing clicks / form events | Freemarker template must be present in Event Body |
| session_id = -1 | Normal during init โ resolves within seconds |
| No data in Autoplay | Confirm autocapture: true in initAll |
| Using wrong ingest URL | Use amplitude_ingest_url, not webhook_url |
| CSP errors | Add *.amplitude.com to connect-src, cdn.amplitude.com to script-src, blob: to worker-src |