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.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. 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
+ ```