chub-dev 0.1.0 → 0.1.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,1199 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: analytics
|
|
3
|
+
description: "Amplitude Analytics Python SDK for server-side event tracking and product analytics"
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "python"
|
|
6
|
+
versions: "1.2.0"
|
|
7
|
+
updated-on: "2026-03-02"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "amplitude,analytics,events,tracking,product"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Amplitude Analytics - Python SDK
|
|
13
|
+
|
|
14
|
+
## Golden Rule
|
|
15
|
+
|
|
16
|
+
**ALWAYS** use `amplitude-analytics` version 1.2.0 or newer for Python server-side instrumentation.
|
|
17
|
+
|
|
18
|
+
This is the official Amplitude backend Python SDK maintained by Amplitude Inc.
|
|
19
|
+
|
|
20
|
+
**DO NOT** use unofficial community packages like `pyamplitude` or `amplitude-python`.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install amplitude-analytics
|
|
28
|
+
```
|
|
29
|
+
```bash
|
|
30
|
+
pip install amplitude-analytics==1.2.0
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Environment Variables Setup
|
|
36
|
+
|
|
37
|
+
Store your API key securely:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# .env file
|
|
41
|
+
AMPLITUDE_API_KEY=your_api_key_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import os
|
|
46
|
+
from dotenv import load_dotenv
|
|
47
|
+
|
|
48
|
+
load_dotenv()
|
|
49
|
+
API_KEY = os.getenv('AMPLITUDE_API_KEY')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Initialization
|
|
55
|
+
|
|
56
|
+
### Basic Initialization
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from amplitude import Amplitude
|
|
60
|
+
|
|
61
|
+
client = Amplitude('YOUR_API_KEY')
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Initialize with Configuration
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from amplitude import Amplitude
|
|
68
|
+
|
|
69
|
+
client = Amplitude(
|
|
70
|
+
api_key='YOUR_API_KEY',
|
|
71
|
+
configuration={
|
|
72
|
+
'flush_queue_size': 200,
|
|
73
|
+
'flush_interval_millis': 10000,
|
|
74
|
+
'flush_max_retries': 12,
|
|
75
|
+
'min_id_length': 5,
|
|
76
|
+
'server_zone': 'US',
|
|
77
|
+
'use_batch': False,
|
|
78
|
+
'opt_out': False
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Configuration Options
|
|
86
|
+
|
|
87
|
+
| Option | Type | Default | Description |
|
|
88
|
+
|--------|------|---------|-------------|
|
|
89
|
+
| `flush_queue_size` | int | 200 | Maximum events before triggering flush |
|
|
90
|
+
| `flush_interval_millis` | int | 10000 | Time between automatic flushes (ms) |
|
|
91
|
+
| `flush_max_retries` | int | 12 | Maximum retry attempts on failure |
|
|
92
|
+
| `min_id_length` | int | 5 | Minimum length for user_id/device_id |
|
|
93
|
+
| `server_zone` | str | 'US' | Data residency: 'US' or 'EU' |
|
|
94
|
+
| `use_batch` | bool | False | Enable batch API endpoint |
|
|
95
|
+
| `opt_out` | bool | False | Disable event processing |
|
|
96
|
+
| `server_url` | str | None | Custom API endpoint URL |
|
|
97
|
+
| `callback` | callable | None | Callback function for responses |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Core API Surfaces
|
|
102
|
+
|
|
103
|
+
### Event Tracking
|
|
104
|
+
|
|
105
|
+
#### Basic Event
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from amplitude import BaseEvent
|
|
109
|
+
|
|
110
|
+
event = BaseEvent(
|
|
111
|
+
event_type="Button Clicked",
|
|
112
|
+
user_id="user@example.com"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
client.track(event)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Event with Device ID
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
event = BaseEvent(
|
|
122
|
+
event_type="Page Viewed",
|
|
123
|
+
device_id="device-123"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
client.track(event)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Event with Properties
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
event = BaseEvent(
|
|
133
|
+
event_type="Product Purchased",
|
|
134
|
+
user_id="user@example.com",
|
|
135
|
+
event_properties={
|
|
136
|
+
"product_id": "SKU-123",
|
|
137
|
+
"price": 29.99,
|
|
138
|
+
"quantity": 2,
|
|
139
|
+
"category": "Electronics"
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
client.track(event)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Advanced Event with All Options
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import time
|
|
150
|
+
|
|
151
|
+
event = BaseEvent(
|
|
152
|
+
event_type="Feature Used",
|
|
153
|
+
user_id="user@example.com",
|
|
154
|
+
device_id="device-123",
|
|
155
|
+
time=int(time.time() * 1000), # Milliseconds
|
|
156
|
+
event_properties={
|
|
157
|
+
"feature_name": "export",
|
|
158
|
+
"feature_category": "data"
|
|
159
|
+
},
|
|
160
|
+
user_properties={
|
|
161
|
+
"plan": "premium",
|
|
162
|
+
"credits": 100
|
|
163
|
+
},
|
|
164
|
+
groups={
|
|
165
|
+
"organization": "acme-corp",
|
|
166
|
+
"team": "engineering"
|
|
167
|
+
},
|
|
168
|
+
group_properties={
|
|
169
|
+
"org_plan": "enterprise",
|
|
170
|
+
"team_size": 50
|
|
171
|
+
},
|
|
172
|
+
app_version="1.2.3",
|
|
173
|
+
platform="Web",
|
|
174
|
+
os_name="MacOS",
|
|
175
|
+
os_version="14.2",
|
|
176
|
+
device_brand="Apple",
|
|
177
|
+
device_manufacturer="Apple",
|
|
178
|
+
device_model="MacBook Pro",
|
|
179
|
+
carrier="N/A",
|
|
180
|
+
country="US",
|
|
181
|
+
region="California",
|
|
182
|
+
city="San Francisco",
|
|
183
|
+
dma="SF-OAK-SJ",
|
|
184
|
+
language="en-US",
|
|
185
|
+
price=9.99,
|
|
186
|
+
quantity=1,
|
|
187
|
+
revenue=9.99,
|
|
188
|
+
product_id="product-123",
|
|
189
|
+
revenue_type="purchase",
|
|
190
|
+
location_lat=37.7749,
|
|
191
|
+
location_lng=-122.4194,
|
|
192
|
+
ip="203.0.113.42",
|
|
193
|
+
idfa="AEBE52E7-03EE-455A-B3C4-E57283966239",
|
|
194
|
+
idfv="BCDEF123-03EE-455A-B3C4-E57283966239",
|
|
195
|
+
adid="CDDEF123-03EE-455A-B3C4-E57283966239",
|
|
196
|
+
android_id="android-123",
|
|
197
|
+
event_id=123456,
|
|
198
|
+
session_id=1234567890,
|
|
199
|
+
insert_id="unique-insert-id-123"
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
client.track(event)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### User Properties
|
|
208
|
+
|
|
209
|
+
#### Create Identify Object
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
from amplitude import Identify
|
|
213
|
+
|
|
214
|
+
identify_obj = Identify()
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### Set Properties
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from amplitude import Identify, EventOptions
|
|
221
|
+
|
|
222
|
+
identify_obj = Identify()
|
|
223
|
+
identify_obj.set("name", "John Doe")
|
|
224
|
+
identify_obj.set("email", "john@example.com")
|
|
225
|
+
identify_obj.set("age", 30)
|
|
226
|
+
identify_obj.set("premium", True)
|
|
227
|
+
|
|
228
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### Set Once (Only if Not Set)
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
identify_obj = Identify()
|
|
235
|
+
identify_obj.set_once("signup_date", "2025-01-01")
|
|
236
|
+
identify_obj.set_once("first_source", "google")
|
|
237
|
+
|
|
238
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Add (Increment Numeric Values)
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
identify_obj = Identify()
|
|
245
|
+
identify_obj.add("login_count", 1)
|
|
246
|
+
identify_obj.add("credits", 100)
|
|
247
|
+
identify_obj.add("points", -50) # Decrement
|
|
248
|
+
|
|
249
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### Append to Array
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
identify_obj = Identify()
|
|
256
|
+
identify_obj.append("visited_pages", "/dashboard")
|
|
257
|
+
identify_obj.append("purchased_products", "SKU-123")
|
|
258
|
+
|
|
259
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Prepend to Array
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
identify_obj = Identify()
|
|
266
|
+
identify_obj.prepend("recent_searches", "laptop")
|
|
267
|
+
|
|
268
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Pre Insert (Add to Beginning if Not Present)
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
identify_obj = Identify()
|
|
275
|
+
identify_obj.pre_insert("badges", "early_adopter")
|
|
276
|
+
|
|
277
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Post Insert (Add to End if Not Present)
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
identify_obj = Identify()
|
|
284
|
+
identify_obj.post_insert("tags", "premium")
|
|
285
|
+
|
|
286
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### Remove from Array
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
identify_obj = Identify()
|
|
293
|
+
identify_obj.remove("blocked_users", "user123")
|
|
294
|
+
|
|
295
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Unset Property
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
identify_obj = Identify()
|
|
302
|
+
identify_obj.unset("temporary_token")
|
|
303
|
+
|
|
304
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### Clear All Properties
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
identify_obj = Identify()
|
|
311
|
+
identify_obj.clear_all()
|
|
312
|
+
|
|
313
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### Chain Multiple Operations
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
identify_obj = (Identify()
|
|
320
|
+
.set("plan", "premium")
|
|
321
|
+
.add("login_count", 1)
|
|
322
|
+
.append("visited_pages", "/checkout")
|
|
323
|
+
.set_once("signup_date", "2025-01-01")
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
client.identify(identify_obj, EventOptions(user_id="user@example.com"))
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### Group Analytics
|
|
332
|
+
|
|
333
|
+
#### Set Single Group
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
from amplitude import EventOptions
|
|
337
|
+
|
|
338
|
+
client.set_group(
|
|
339
|
+
group_type="organization",
|
|
340
|
+
group_name="acme-corp",
|
|
341
|
+
event_options=EventOptions(user_id="user@example.com")
|
|
342
|
+
)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Set Multiple Groups
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
client.set_group(
|
|
349
|
+
group_type="teams",
|
|
350
|
+
group_name=["engineering", "product", "design"],
|
|
351
|
+
event_options=EventOptions(user_id="user@example.com")
|
|
352
|
+
)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### Set Group Properties
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
from amplitude import Identify
|
|
359
|
+
|
|
360
|
+
identify_obj = Identify()
|
|
361
|
+
identify_obj.set("plan", "enterprise")
|
|
362
|
+
identify_obj.set("seats", 100)
|
|
363
|
+
identify_obj.set("industry", "technology")
|
|
364
|
+
|
|
365
|
+
client.group_identify(
|
|
366
|
+
group_type="organization",
|
|
367
|
+
group_name="acme-corp",
|
|
368
|
+
identify_obj=identify_obj,
|
|
369
|
+
event_options=EventOptions(user_id="user@example.com")
|
|
370
|
+
)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### Event-Level Groups
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
event = BaseEvent(
|
|
377
|
+
event_type="Feature Used",
|
|
378
|
+
user_id="user@example.com",
|
|
379
|
+
groups={
|
|
380
|
+
"organization": "acme-corp",
|
|
381
|
+
"department": "sales"
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
client.track(event)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
### Revenue Tracking
|
|
391
|
+
|
|
392
|
+
#### Basic Revenue
|
|
393
|
+
|
|
394
|
+
```python
|
|
395
|
+
from amplitude import Revenue, EventOptions
|
|
396
|
+
|
|
397
|
+
revenue = Revenue(
|
|
398
|
+
price=9.99,
|
|
399
|
+
quantity=1,
|
|
400
|
+
product_id="com.company.product"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
client.revenue(revenue, EventOptions(user_id="user@example.com"))
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### Advanced Revenue Tracking
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
revenue = Revenue(
|
|
410
|
+
price=29.99,
|
|
411
|
+
quantity=2,
|
|
412
|
+
product_id="SKU-123",
|
|
413
|
+
revenue_type="purchase",
|
|
414
|
+
receipt="receipt-id-12345",
|
|
415
|
+
receipt_sig="signature-abc",
|
|
416
|
+
properties={
|
|
417
|
+
"region": "US",
|
|
418
|
+
"currency": "USD",
|
|
419
|
+
"payment_method": "credit_card",
|
|
420
|
+
"discount_applied": True
|
|
421
|
+
}
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
client.revenue(revenue, EventOptions(user_id="user@example.com"))
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### Plugin System
|
|
430
|
+
|
|
431
|
+
#### Enrichment Plugin
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
from amplitude import EventPlugin, PluginType
|
|
435
|
+
import platform
|
|
436
|
+
|
|
437
|
+
class SystemInfoPlugin(EventPlugin):
|
|
438
|
+
def __init__(self):
|
|
439
|
+
self.plugin_type = PluginType.ENRICHMENT
|
|
440
|
+
self.configuration = None
|
|
441
|
+
|
|
442
|
+
def setup(self, client):
|
|
443
|
+
self.configuration = client.configuration
|
|
444
|
+
print("System Info Plugin initialized")
|
|
445
|
+
|
|
446
|
+
def execute(self, event):
|
|
447
|
+
if event.event_properties is None:
|
|
448
|
+
event.event_properties = {}
|
|
449
|
+
|
|
450
|
+
event.event_properties.update({
|
|
451
|
+
'plugin_system': platform.system(),
|
|
452
|
+
'plugin_python_version': platform.python_version(),
|
|
453
|
+
'plugin_timestamp': int(time.time() * 1000)
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
return event
|
|
457
|
+
|
|
458
|
+
client.add(SystemInfoPlugin())
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### Destination Plugin
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
import requests
|
|
465
|
+
|
|
466
|
+
class CustomAnalyticsPlugin(EventPlugin):
|
|
467
|
+
def __init__(self, api_url, api_token):
|
|
468
|
+
self.plugin_type = PluginType.DESTINATION
|
|
469
|
+
self.api_url = api_url
|
|
470
|
+
self.api_token = api_token
|
|
471
|
+
self.configuration = None
|
|
472
|
+
|
|
473
|
+
def setup(self, client):
|
|
474
|
+
self.configuration = client.configuration
|
|
475
|
+
print("Custom Analytics Plugin initialized")
|
|
476
|
+
|
|
477
|
+
def execute(self, event):
|
|
478
|
+
try:
|
|
479
|
+
response = requests.post(
|
|
480
|
+
self.api_url,
|
|
481
|
+
headers={
|
|
482
|
+
'Content-Type': 'application/json',
|
|
483
|
+
'Authorization': f'Bearer {self.api_token}'
|
|
484
|
+
},
|
|
485
|
+
json={
|
|
486
|
+
'event_type': event.event_type,
|
|
487
|
+
'user_id': event.user_id,
|
|
488
|
+
'properties': event.event_properties
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
return event
|
|
493
|
+
except Exception as e:
|
|
494
|
+
print(f"Error sending to custom analytics: {e}")
|
|
495
|
+
return event
|
|
496
|
+
|
|
497
|
+
client.add(CustomAnalyticsPlugin(
|
|
498
|
+
api_url='https://api.custom-analytics.com/events',
|
|
499
|
+
api_token='your_token_here'
|
|
500
|
+
))
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
#### Remove Plugin
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
client.remove("plugin-name")
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
### Buffer Management
|
|
512
|
+
|
|
513
|
+
#### Flush Events Immediately
|
|
514
|
+
|
|
515
|
+
```python
|
|
516
|
+
client.flush()
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
#### Async Flush with Callback
|
|
520
|
+
|
|
521
|
+
```python
|
|
522
|
+
def flush_callback(code, message):
|
|
523
|
+
if code == 200:
|
|
524
|
+
print("Flush successful")
|
|
525
|
+
else:
|
|
526
|
+
print(f"Flush failed: {message}")
|
|
527
|
+
|
|
528
|
+
client.flush(callback=flush_callback)
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
### Shutdown
|
|
534
|
+
|
|
535
|
+
```python
|
|
536
|
+
# Flush remaining events and close client
|
|
537
|
+
client.shutdown()
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
### Opt-Out Control
|
|
543
|
+
|
|
544
|
+
```python
|
|
545
|
+
# Disable tracking
|
|
546
|
+
client.configuration.opt_out = True
|
|
547
|
+
|
|
548
|
+
# Enable tracking
|
|
549
|
+
client.configuration.opt_out = False
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Event Options
|
|
555
|
+
|
|
556
|
+
```python
|
|
557
|
+
from amplitude import EventOptions
|
|
558
|
+
|
|
559
|
+
options = EventOptions(
|
|
560
|
+
user_id="user@example.com",
|
|
561
|
+
device_id="device-123",
|
|
562
|
+
session_id=1234567890,
|
|
563
|
+
app_version="1.2.3",
|
|
564
|
+
platform="Web",
|
|
565
|
+
os_name="MacOS",
|
|
566
|
+
os_version="14.2",
|
|
567
|
+
device_brand="Apple",
|
|
568
|
+
device_manufacturer="Apple",
|
|
569
|
+
device_model="MacBook Pro",
|
|
570
|
+
carrier="N/A",
|
|
571
|
+
country="US",
|
|
572
|
+
region="California",
|
|
573
|
+
city="San Francisco",
|
|
574
|
+
language="en-US",
|
|
575
|
+
ip="203.0.113.42"
|
|
576
|
+
)
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## Common Patterns
|
|
582
|
+
|
|
583
|
+
### Initialize with Environment Variables
|
|
584
|
+
|
|
585
|
+
```python
|
|
586
|
+
import os
|
|
587
|
+
from amplitude import Amplitude
|
|
588
|
+
|
|
589
|
+
API_KEY = os.environ.get('AMPLITUDE_API_KEY')
|
|
590
|
+
|
|
591
|
+
if not API_KEY:
|
|
592
|
+
raise ValueError("AMPLITUDE_API_KEY environment variable not set")
|
|
593
|
+
|
|
594
|
+
client = Amplitude(API_KEY)
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### Track User Signup
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
from amplitude import BaseEvent, Identify, EventOptions
|
|
601
|
+
|
|
602
|
+
# Track signup event
|
|
603
|
+
event = BaseEvent(
|
|
604
|
+
event_type="User Signed Up",
|
|
605
|
+
user_id="new_user@example.com",
|
|
606
|
+
event_properties={
|
|
607
|
+
"signup_method": "google",
|
|
608
|
+
"referral_source": "friend"
|
|
609
|
+
}
|
|
610
|
+
)
|
|
611
|
+
client.track(event)
|
|
612
|
+
|
|
613
|
+
# Set initial user properties
|
|
614
|
+
identify = Identify()
|
|
615
|
+
identify.set("signup_date", "2025-01-07")
|
|
616
|
+
identify.set("plan", "free")
|
|
617
|
+
identify.set_once("first_source", "google")
|
|
618
|
+
|
|
619
|
+
client.identify(identify, EventOptions(user_id="new_user@example.com"))
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Track Page Views
|
|
623
|
+
|
|
624
|
+
```python
|
|
625
|
+
event = BaseEvent(
|
|
626
|
+
event_type="Page Viewed",
|
|
627
|
+
user_id="user@example.com",
|
|
628
|
+
event_properties={
|
|
629
|
+
"page_url": "/dashboard",
|
|
630
|
+
"page_title": "Dashboard",
|
|
631
|
+
"referrer": "/home"
|
|
632
|
+
}
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
client.track(event)
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Track API Requests
|
|
639
|
+
|
|
640
|
+
```python
|
|
641
|
+
import time
|
|
642
|
+
|
|
643
|
+
start_time = time.time()
|
|
644
|
+
|
|
645
|
+
# Make API request
|
|
646
|
+
response = requests.get('https://api.example.com/data')
|
|
647
|
+
|
|
648
|
+
duration_ms = int((time.time() - start_time) * 1000)
|
|
649
|
+
|
|
650
|
+
event = BaseEvent(
|
|
651
|
+
event_type="API Request",
|
|
652
|
+
user_id="user@example.com",
|
|
653
|
+
event_properties={
|
|
654
|
+
"endpoint": "/data",
|
|
655
|
+
"method": "GET",
|
|
656
|
+
"status_code": response.status_code,
|
|
657
|
+
"duration_ms": duration_ms
|
|
658
|
+
}
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
client.track(event)
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Track Errors
|
|
665
|
+
|
|
666
|
+
```python
|
|
667
|
+
try:
|
|
668
|
+
# Some operation
|
|
669
|
+
result = perform_operation()
|
|
670
|
+
except Exception as e:
|
|
671
|
+
event = BaseEvent(
|
|
672
|
+
event_type="Error Occurred",
|
|
673
|
+
user_id="user@example.com",
|
|
674
|
+
event_properties={
|
|
675
|
+
"error_type": type(e).__name__,
|
|
676
|
+
"error_message": str(e),
|
|
677
|
+
"function_name": "perform_operation"
|
|
678
|
+
}
|
|
679
|
+
)
|
|
680
|
+
client.track(event)
|
|
681
|
+
raise
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
|
|
686
|
+
## Flask Integration
|
|
687
|
+
|
|
688
|
+
```python
|
|
689
|
+
from flask import Flask, request, g
|
|
690
|
+
from amplitude import Amplitude, BaseEvent
|
|
691
|
+
|
|
692
|
+
app = Flask(__name__)
|
|
693
|
+
amplitude_client = Amplitude(os.environ['AMPLITUDE_API_KEY'])
|
|
694
|
+
|
|
695
|
+
@app.before_request
|
|
696
|
+
def before_request():
|
|
697
|
+
g.user_id = request.headers.get('X-User-ID')
|
|
698
|
+
|
|
699
|
+
@app.after_request
|
|
700
|
+
def after_request(response):
|
|
701
|
+
if g.user_id:
|
|
702
|
+
event = BaseEvent(
|
|
703
|
+
event_type="API Request",
|
|
704
|
+
user_id=g.user_id,
|
|
705
|
+
event_properties={
|
|
706
|
+
"method": request.method,
|
|
707
|
+
"path": request.path,
|
|
708
|
+
"status_code": response.status_code
|
|
709
|
+
}
|
|
710
|
+
)
|
|
711
|
+
amplitude_client.track(event)
|
|
712
|
+
|
|
713
|
+
return response
|
|
714
|
+
|
|
715
|
+
@app.route('/api/action')
|
|
716
|
+
def api_action():
|
|
717
|
+
amplitude_client.track(BaseEvent(
|
|
718
|
+
event_type="Action Performed",
|
|
719
|
+
user_id=g.user_id,
|
|
720
|
+
event_properties={
|
|
721
|
+
"action": "api_action"
|
|
722
|
+
}
|
|
723
|
+
))
|
|
724
|
+
return {"status": "success"}
|
|
725
|
+
|
|
726
|
+
if __name__ == '__main__':
|
|
727
|
+
try:
|
|
728
|
+
app.run()
|
|
729
|
+
finally:
|
|
730
|
+
amplitude_client.shutdown()
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
## Django Integration
|
|
736
|
+
|
|
737
|
+
```python
|
|
738
|
+
# middleware.py
|
|
739
|
+
from amplitude import Amplitude, BaseEvent
|
|
740
|
+
import os
|
|
741
|
+
|
|
742
|
+
amplitude_client = Amplitude(os.environ.get('AMPLITUDE_API_KEY'))
|
|
743
|
+
|
|
744
|
+
class AmplitudeMiddleware:
|
|
745
|
+
def __init__(self, get_response):
|
|
746
|
+
self.get_response = get_response
|
|
747
|
+
|
|
748
|
+
def __call__(self, request):
|
|
749
|
+
response = self.get_response(request)
|
|
750
|
+
|
|
751
|
+
if hasattr(request, 'user') and request.user.is_authenticated:
|
|
752
|
+
event = BaseEvent(
|
|
753
|
+
event_type="Page Viewed",
|
|
754
|
+
user_id=str(request.user.id),
|
|
755
|
+
event_properties={
|
|
756
|
+
"path": request.path,
|
|
757
|
+
"method": request.method,
|
|
758
|
+
"status_code": response.status_code
|
|
759
|
+
}
|
|
760
|
+
)
|
|
761
|
+
amplitude_client.track(event)
|
|
762
|
+
|
|
763
|
+
return response
|
|
764
|
+
|
|
765
|
+
# settings.py
|
|
766
|
+
MIDDLEWARE = [
|
|
767
|
+
# ... other middleware
|
|
768
|
+
'myapp.middleware.AmplitudeMiddleware',
|
|
769
|
+
]
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
## FastAPI Integration
|
|
775
|
+
|
|
776
|
+
```python
|
|
777
|
+
from fastapi import FastAPI, Request, Depends
|
|
778
|
+
from amplitude import Amplitude, BaseEvent
|
|
779
|
+
import os
|
|
780
|
+
|
|
781
|
+
app = FastAPI()
|
|
782
|
+
amplitude_client = Amplitude(os.environ['AMPLITUDE_API_KEY'])
|
|
783
|
+
|
|
784
|
+
@app.middleware("http")
|
|
785
|
+
async def amplitude_middleware(request: Request, call_next):
|
|
786
|
+
response = await call_next(request)
|
|
787
|
+
|
|
788
|
+
user_id = request.headers.get('X-User-ID')
|
|
789
|
+
if user_id:
|
|
790
|
+
event = BaseEvent(
|
|
791
|
+
event_type="API Request",
|
|
792
|
+
user_id=user_id,
|
|
793
|
+
event_properties={
|
|
794
|
+
"method": request.method,
|
|
795
|
+
"path": request.url.path,
|
|
796
|
+
"status_code": response.status_code
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
amplitude_client.track(event)
|
|
800
|
+
|
|
801
|
+
return response
|
|
802
|
+
|
|
803
|
+
@app.on_event("shutdown")
|
|
804
|
+
async def shutdown_event():
|
|
805
|
+
amplitude_client.shutdown()
|
|
806
|
+
|
|
807
|
+
@app.post("/action")
|
|
808
|
+
async def perform_action(user_id: str):
|
|
809
|
+
amplitude_client.track(BaseEvent(
|
|
810
|
+
event_type="Action Performed",
|
|
811
|
+
user_id=user_id,
|
|
812
|
+
event_properties={
|
|
813
|
+
"action": "perform_action"
|
|
814
|
+
}
|
|
815
|
+
))
|
|
816
|
+
return {"status": "success"}
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## Celery Integration
|
|
822
|
+
|
|
823
|
+
```python
|
|
824
|
+
from celery import Celery
|
|
825
|
+
from amplitude import Amplitude, BaseEvent
|
|
826
|
+
import os
|
|
827
|
+
|
|
828
|
+
app = Celery('tasks', broker='redis://localhost:6379/0')
|
|
829
|
+
amplitude_client = Amplitude(os.environ['AMPLITUDE_API_KEY'])
|
|
830
|
+
|
|
831
|
+
@app.task
|
|
832
|
+
def process_order(order_id, user_id):
|
|
833
|
+
# Process order
|
|
834
|
+
result = process_order_logic(order_id)
|
|
835
|
+
|
|
836
|
+
# Track event
|
|
837
|
+
event = BaseEvent(
|
|
838
|
+
event_type="Order Processed",
|
|
839
|
+
user_id=user_id,
|
|
840
|
+
event_properties={
|
|
841
|
+
"order_id": order_id,
|
|
842
|
+
"status": result.status,
|
|
843
|
+
"processing_time_ms": result.duration
|
|
844
|
+
}
|
|
845
|
+
)
|
|
846
|
+
amplitude_client.track(event)
|
|
847
|
+
|
|
848
|
+
return result
|
|
849
|
+
|
|
850
|
+
@app.on_after_finalize.connect
|
|
851
|
+
def shutdown_amplitude(sender, **kwargs):
|
|
852
|
+
amplitude_client.shutdown()
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
---
|
|
856
|
+
|
|
857
|
+
## Batch Event Tracking
|
|
858
|
+
|
|
859
|
+
```python
|
|
860
|
+
from amplitude import BaseEvent
|
|
861
|
+
|
|
862
|
+
events = [
|
|
863
|
+
BaseEvent(
|
|
864
|
+
event_type="Event 1",
|
|
865
|
+
user_id="user@example.com",
|
|
866
|
+
event_properties={"property": "value1"}
|
|
867
|
+
),
|
|
868
|
+
BaseEvent(
|
|
869
|
+
event_type="Event 2",
|
|
870
|
+
user_id="user@example.com",
|
|
871
|
+
event_properties={"property": "value2"}
|
|
872
|
+
),
|
|
873
|
+
BaseEvent(
|
|
874
|
+
event_type="Event 3",
|
|
875
|
+
user_id="user@example.com",
|
|
876
|
+
event_properties={"property": "value3"}
|
|
877
|
+
)
|
|
878
|
+
]
|
|
879
|
+
|
|
880
|
+
for event in events:
|
|
881
|
+
client.track(event)
|
|
882
|
+
|
|
883
|
+
# Flush all events
|
|
884
|
+
client.flush()
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
## EU Data Residency
|
|
890
|
+
|
|
891
|
+
```python
|
|
892
|
+
client = Amplitude(
|
|
893
|
+
api_key='YOUR_API_KEY',
|
|
894
|
+
configuration={
|
|
895
|
+
'server_zone': 'EU'
|
|
896
|
+
}
|
|
897
|
+
)
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
---
|
|
901
|
+
|
|
902
|
+
## Custom Server URL
|
|
903
|
+
|
|
904
|
+
```python
|
|
905
|
+
client = Amplitude(
|
|
906
|
+
api_key='YOUR_API_KEY',
|
|
907
|
+
configuration={
|
|
908
|
+
'server_url': 'https://proxy.example.com/amplitude'
|
|
909
|
+
}
|
|
910
|
+
)
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
---
|
|
914
|
+
|
|
915
|
+
## Use Batch API Endpoint
|
|
916
|
+
|
|
917
|
+
```python
|
|
918
|
+
client = Amplitude(
|
|
919
|
+
api_key='YOUR_API_KEY',
|
|
920
|
+
configuration={
|
|
921
|
+
'use_batch': True
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
## Event Callback
|
|
929
|
+
|
|
930
|
+
```python
|
|
931
|
+
def event_callback(event, code, message):
|
|
932
|
+
if code == 200:
|
|
933
|
+
print(f"Event '{event.event_type}' sent successfully")
|
|
934
|
+
else:
|
|
935
|
+
print(f"Failed to send event: {message}")
|
|
936
|
+
|
|
937
|
+
client = Amplitude(
|
|
938
|
+
api_key='YOUR_API_KEY',
|
|
939
|
+
configuration={
|
|
940
|
+
'callback': event_callback
|
|
941
|
+
}
|
|
942
|
+
)
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
---
|
|
946
|
+
|
|
947
|
+
## HTTP API Direct Usage
|
|
948
|
+
|
|
949
|
+
### Basic Request
|
|
950
|
+
|
|
951
|
+
```python
|
|
952
|
+
import requests
|
|
953
|
+
import time
|
|
954
|
+
|
|
955
|
+
payload = {
|
|
956
|
+
"api_key": "YOUR_API_KEY",
|
|
957
|
+
"events": [
|
|
958
|
+
{
|
|
959
|
+
"user_id": "user@example.com",
|
|
960
|
+
"device_id": "device-123",
|
|
961
|
+
"event_type": "Page Viewed",
|
|
962
|
+
"time": int(time.time() * 1000),
|
|
963
|
+
"event_properties": {
|
|
964
|
+
"page": "homepage"
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
]
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
response = requests.post(
|
|
971
|
+
'https://api2.amplitude.com/2/httpapi',
|
|
972
|
+
json=payload
|
|
973
|
+
)
|
|
974
|
+
|
|
975
|
+
print(response.json())
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
### Batch Request
|
|
979
|
+
|
|
980
|
+
```python
|
|
981
|
+
payload = {
|
|
982
|
+
"api_key": "YOUR_API_KEY",
|
|
983
|
+
"events": [
|
|
984
|
+
{
|
|
985
|
+
"user_id": "user1@example.com",
|
|
986
|
+
"event_type": "Event 1",
|
|
987
|
+
"time": int(time.time() * 1000)
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
"user_id": "user2@example.com",
|
|
991
|
+
"event_type": "Event 2",
|
|
992
|
+
"time": int(time.time() * 1000)
|
|
993
|
+
}
|
|
994
|
+
]
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
response = requests.post(
|
|
998
|
+
'https://api2.amplitude.com/2/httpapi',
|
|
999
|
+
json=payload
|
|
1000
|
+
)
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
### EU Endpoint
|
|
1004
|
+
|
|
1005
|
+
```python
|
|
1006
|
+
response = requests.post(
|
|
1007
|
+
'https://api.eu.amplitude.com/2/httpapi',
|
|
1008
|
+
json=payload
|
|
1009
|
+
)
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
## Threading Considerations
|
|
1015
|
+
|
|
1016
|
+
The SDK is thread-safe and automatically manages background threads for event flushing.
|
|
1017
|
+
|
|
1018
|
+
```python
|
|
1019
|
+
import threading
|
|
1020
|
+
from amplitude import Amplitude, BaseEvent
|
|
1021
|
+
|
|
1022
|
+
client = Amplitude('YOUR_API_KEY')
|
|
1023
|
+
|
|
1024
|
+
def worker(user_id):
|
|
1025
|
+
for i in range(10):
|
|
1026
|
+
event = BaseEvent(
|
|
1027
|
+
event_type="Worker Event",
|
|
1028
|
+
user_id=user_id,
|
|
1029
|
+
event_properties={
|
|
1030
|
+
"iteration": i
|
|
1031
|
+
}
|
|
1032
|
+
)
|
|
1033
|
+
client.track(event)
|
|
1034
|
+
|
|
1035
|
+
threads = []
|
|
1036
|
+
for i in range(5):
|
|
1037
|
+
thread = threading.Thread(target=worker, args=(f"user{i}@example.com",))
|
|
1038
|
+
threads.append(thread)
|
|
1039
|
+
thread.start()
|
|
1040
|
+
|
|
1041
|
+
for thread in threads:
|
|
1042
|
+
thread.join()
|
|
1043
|
+
|
|
1044
|
+
client.shutdown()
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
---
|
|
1048
|
+
|
|
1049
|
+
## Logging Configuration
|
|
1050
|
+
|
|
1051
|
+
```python
|
|
1052
|
+
import logging
|
|
1053
|
+
|
|
1054
|
+
# Enable debug logging
|
|
1055
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
1056
|
+
|
|
1057
|
+
client = Amplitude('YOUR_API_KEY')
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
---
|
|
1061
|
+
|
|
1062
|
+
## Testing
|
|
1063
|
+
|
|
1064
|
+
### Mock Amplitude for Tests
|
|
1065
|
+
|
|
1066
|
+
```python
|
|
1067
|
+
from unittest.mock import Mock, patch
|
|
1068
|
+
import pytest
|
|
1069
|
+
|
|
1070
|
+
@pytest.fixture
|
|
1071
|
+
def mock_amplitude():
|
|
1072
|
+
with patch('amplitude.Amplitude') as mock:
|
|
1073
|
+
yield mock
|
|
1074
|
+
|
|
1075
|
+
def test_event_tracking(mock_amplitude):
|
|
1076
|
+
client = mock_amplitude.return_value
|
|
1077
|
+
|
|
1078
|
+
event = BaseEvent(
|
|
1079
|
+
event_type="Test Event",
|
|
1080
|
+
user_id="test_user"
|
|
1081
|
+
)
|
|
1082
|
+
|
|
1083
|
+
client.track(event)
|
|
1084
|
+
client.track.assert_called_once()
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
---
|
|
1088
|
+
|
|
1089
|
+
## Error Handling
|
|
1090
|
+
|
|
1091
|
+
```python
|
|
1092
|
+
from amplitude import Amplitude, BaseEvent
|
|
1093
|
+
|
|
1094
|
+
try:
|
|
1095
|
+
client = Amplitude('YOUR_API_KEY')
|
|
1096
|
+
|
|
1097
|
+
event = BaseEvent(
|
|
1098
|
+
event_type="Test Event",
|
|
1099
|
+
user_id="user@example.com"
|
|
1100
|
+
)
|
|
1101
|
+
|
|
1102
|
+
client.track(event)
|
|
1103
|
+
client.flush()
|
|
1104
|
+
|
|
1105
|
+
except Exception as e:
|
|
1106
|
+
print(f"Error tracking event: {e}")
|
|
1107
|
+
|
|
1108
|
+
finally:
|
|
1109
|
+
client.shutdown()
|
|
1110
|
+
```
|
|
1111
|
+
|
|
1112
|
+
---
|
|
1113
|
+
|
|
1114
|
+
## Constraints & Limits
|
|
1115
|
+
|
|
1116
|
+
- **Minimum ID length:** 5 characters (configurable via `min_id_length`)
|
|
1117
|
+
- **Event batch size:** 200 events by default (`flush_queue_size`)
|
|
1118
|
+
- **Flush interval:** 10 seconds by default (`flush_interval_millis`)
|
|
1119
|
+
- **User ID or Device ID required:** At least one must be provided
|
|
1120
|
+
- **Python version:** Requires Python >= 3.6 and < 4
|
|
1121
|
+
|
|
1122
|
+
---
|
|
1123
|
+
|
|
1124
|
+
## Complete Example
|
|
1125
|
+
|
|
1126
|
+
```python
|
|
1127
|
+
import os
|
|
1128
|
+
from amplitude import Amplitude, BaseEvent, Identify, Revenue, EventOptions
|
|
1129
|
+
from dotenv import load_dotenv
|
|
1130
|
+
|
|
1131
|
+
# Load environment variables
|
|
1132
|
+
load_dotenv()
|
|
1133
|
+
|
|
1134
|
+
# Initialize client
|
|
1135
|
+
client = Amplitude(
|
|
1136
|
+
api_key=os.environ['AMPLITUDE_API_KEY'],
|
|
1137
|
+
configuration={
|
|
1138
|
+
'flush_queue_size': 100,
|
|
1139
|
+
'flush_interval_millis': 5000,
|
|
1140
|
+
'server_zone': 'US'
|
|
1141
|
+
}
|
|
1142
|
+
)
|
|
1143
|
+
|
|
1144
|
+
try:
|
|
1145
|
+
# Track user signup
|
|
1146
|
+
signup_event = BaseEvent(
|
|
1147
|
+
event_type="User Signed Up",
|
|
1148
|
+
user_id="user@example.com",
|
|
1149
|
+
event_properties={
|
|
1150
|
+
"signup_method": "email",
|
|
1151
|
+
"referral_source": "organic"
|
|
1152
|
+
}
|
|
1153
|
+
)
|
|
1154
|
+
client.track(signup_event)
|
|
1155
|
+
|
|
1156
|
+
# Set user properties
|
|
1157
|
+
identify = Identify()
|
|
1158
|
+
identify.set("name", "John Doe")
|
|
1159
|
+
identify.set("email", "user@example.com")
|
|
1160
|
+
identify.set("plan", "free")
|
|
1161
|
+
identify.set_once("signup_date", "2025-01-07")
|
|
1162
|
+
|
|
1163
|
+
client.identify(identify, EventOptions(user_id="user@example.com"))
|
|
1164
|
+
|
|
1165
|
+
# Set group
|
|
1166
|
+
client.set_group(
|
|
1167
|
+
group_type="organization",
|
|
1168
|
+
group_name="acme-corp",
|
|
1169
|
+
event_options=EventOptions(user_id="user@example.com")
|
|
1170
|
+
)
|
|
1171
|
+
|
|
1172
|
+
# Track purchase
|
|
1173
|
+
purchase_event = BaseEvent(
|
|
1174
|
+
event_type="Product Purchased",
|
|
1175
|
+
user_id="user@example.com",
|
|
1176
|
+
event_properties={
|
|
1177
|
+
"product_id": "SKU-123",
|
|
1178
|
+
"product_name": "Premium Plan",
|
|
1179
|
+
"category": "subscription"
|
|
1180
|
+
}
|
|
1181
|
+
)
|
|
1182
|
+
client.track(purchase_event)
|
|
1183
|
+
|
|
1184
|
+
# Track revenue
|
|
1185
|
+
revenue = Revenue(
|
|
1186
|
+
price=29.99,
|
|
1187
|
+
quantity=1,
|
|
1188
|
+
product_id="SKU-123",
|
|
1189
|
+
revenue_type="purchase"
|
|
1190
|
+
)
|
|
1191
|
+
client.revenue(revenue, EventOptions(user_id="user@example.com"))
|
|
1192
|
+
|
|
1193
|
+
# Flush all events
|
|
1194
|
+
client.flush()
|
|
1195
|
+
|
|
1196
|
+
finally:
|
|
1197
|
+
# Clean shutdown
|
|
1198
|
+
client.shutdown()
|
|
1199
|
+
```
|