vybekiit 0.7.3 → 0.7.7
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/dist/bin.js +16607 -7527
- package/dist/global-skills/aws-cdk/SKILL.md +2 -1
- package/dist/global-skills/aws-cloudformation/SKILL.md +2 -1
- package/dist/global-skills/aws-serverless/SKILL.md +45 -44
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +2 -1
- package/dist/global-skills/aws-serverless/references/api-gateway.md +50 -470
- package/dist/global-skills/aws-serverless/references/architecture.md +47 -186
- package/dist/global-skills/aws-serverless/references/concurrency.md +44 -158
- package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
- package/dist/global-skills/aws-serverless/references/event-sources.md +72 -391
- package/dist/global-skills/aws-serverless/references/lambda.md +69 -428
- package/dist/global-skills/aws-serverless/references/orchestration.md +65 -384
- package/dist/global-skills/aws-serverless/references/production.md +78 -415
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +92 -619
- package/dist/global-skills/claimable-postgres/SKILL.md +60 -49
- package/dist/global-skills/design-my-data/SKILL.md +2 -0
- package/dist/global-skills/eas-app-stores/SKILL.md +8 -0
- package/dist/global-skills/eas-app-stores/references/play-store.md +2 -0
- package/dist/global-skills/eas-hosting/SKILL.md +8 -0
- package/dist/global-skills/eas-observe/SKILL.md +30 -8
- package/dist/global-skills/eas-observe/agents/openai.yaml +1 -1
- package/dist/global-skills/eas-observe/references/metrics.md +54 -3
- package/dist/global-skills/eas-observe/references/queries.md +78 -17
- package/dist/global-skills/eas-observe/references/setup.md +164 -5
- package/dist/global-skills/eas-observe/references/third-party.md +136 -0
- package/dist/global-skills/eas-simulator/SKILL.md +63 -11
- package/dist/global-skills/eas-simulator/references/controllers.md +21 -2
- package/dist/global-skills/eas-simulator/references/run-your-app.md +16 -11
- package/dist/global-skills/eas-simulator/references/troubleshooting.md +8 -5
- package/dist/global-skills/eas-update-insights/SKILL.md +8 -0
- package/dist/global-skills/eas-workflows/SKILL.md +15 -10
- package/dist/global-skills/eas-workflows/scripts/package.json +2 -7
- package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +30 -0
- package/dist/global-skills/email-best-practices/README.md +63 -0
- package/dist/global-skills/email-best-practices/references/accessibility.md +189 -0
- package/dist/global-skills/email-best-practices/references/compliance.md +125 -0
- package/dist/global-skills/email-best-practices/references/deliverability.md +121 -0
- package/dist/global-skills/email-best-practices/references/email-capture.md +129 -0
- package/dist/global-skills/email-best-practices/references/email-types.md +173 -0
- package/dist/global-skills/email-best-practices/references/list-management.md +157 -0
- package/dist/global-skills/email-best-practices/references/marketing-emails.md +115 -0
- package/dist/global-skills/email-best-practices/references/sending-reliability.md +155 -0
- package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +418 -0
- package/dist/global-skills/email-best-practices/references/transactional-emails.md +92 -0
- package/dist/global-skills/email-best-practices/references/webhooks-events.md +167 -0
- package/dist/global-skills/email-best-practices/tests/README.md +35 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +46 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +48 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +36 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +52 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +51 -0
- package/dist/global-skills/expo-animation/LICENSE +21 -0
- package/dist/global-skills/expo-animation/RECIPES.md +385 -0
- package/dist/global-skills/expo-animation/SKILL.md +267 -0
- package/dist/global-skills/expo-animation/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-app-clip/SKILL.md +8 -0
- package/dist/global-skills/expo-brownfield/SKILL.md +8 -0
- package/dist/global-skills/expo-brownfield/references/brownfield-isolated.md +53 -4
- package/dist/global-skills/expo-data-fetching/SKILL.md +8 -0
- package/dist/global-skills/expo-design-system/SKILL.md +356 -0
- package/dist/global-skills/expo-design-system/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-design-system/references/audit.md +185 -0
- package/dist/global-skills/expo-dev-client/SKILL.md +8 -0
- package/dist/global-skills/expo-dom/SKILL.md +8 -0
- package/dist/global-skills/expo-examples/SKILL.md +8 -0
- package/dist/global-skills/expo-migrate-module/SKILL.md +113 -0
- package/dist/global-skills/expo-migrate-module/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-migrate-module/references/compatibility.md +73 -0
- package/dist/global-skills/expo-migrate-module/references/example.md +212 -0
- package/dist/global-skills/expo-migrate-module/references/migration-map.md +306 -0
- package/dist/global-skills/expo-module/SKILL.md +11 -1
- package/dist/global-skills/expo-native-ui/SKILL.md +8 -0
- package/dist/global-skills/expo-project-structure/SKILL.md +114 -0
- package/dist/global-skills/expo-project-structure/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-router/SKILL.md +8 -0
- package/dist/global-skills/expo-skill-feedback/SKILL.md +66 -33
- package/dist/global-skills/expo-skill-feedback/agents/openai.yaml +2 -2
- package/dist/global-skills/expo-tailwind-setup/SKILL.md +8 -0
- package/dist/global-skills/expo-ui/SKILL.md +8 -0
- package/dist/global-skills/expo-upgrade/SKILL.md +15 -1
- package/dist/global-skills/expo-web-to-native/SKILL.md +8 -0
- package/dist/global-skills/extension-to-functions-codebase/SKILL.md +129 -0
- package/dist/global-skills/extension-to-functions-codebase/references/configuration-migration.md +161 -0
- package/dist/global-skills/extension-to-functions-codebase/references/destructuring-shim.md +122 -0
- package/dist/global-skills/extension-to-functions-codebase/references/signature-mapping.md +84 -0
- package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +61 -19
- package/dist/global-skills/firebase-ai-logic-basics/references/flutter_setup.md +6 -3
- package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +5 -1
- package/dist/global-skills/firebase-auth-basics/SKILL.md +4 -2
- package/dist/global-skills/firebase-basics/SKILL.md +5 -5
- package/dist/global-skills/firebase-crashlytics/SKILL.md +2 -0
- package/dist/global-skills/firebase-data-connect/SKILL.md +2 -0
- package/dist/global-skills/firebase-firestore/SKILL.md +3 -6
- package/dist/global-skills/firebase-hosting-basics/SKILL.md +4 -1
- package/dist/global-skills/firebase-remote-config-basics/SKILL.md +5 -1
- package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +4 -1
- package/dist/global-skills/harden/SKILL.md +2 -1
- package/dist/global-skills/instrument-feature-flags/SKILL.md +1 -0
- package/dist/global-skills/instrument-feature-flags/references/COMMANDMENTS.md +5 -0
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/android.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/api.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/django.md +38 -5
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +10 -4
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/flask.md +17 -5
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +7 -5
- package/dist/global-skills/instrument-feature-flags/references/go.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ios.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/java.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +74 -8
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/php.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/python.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/react.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/rust.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/usage.md +41 -4
- package/dist/global-skills/instrument-feature-flags/references/web.md +7 -5
- package/dist/global-skills/instrument-product-analytics/SKILL.md +2 -1
- package/dist/global-skills/instrument-product-analytics/references/COMMANDMENTS.md +5 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-hybrid.md +12 -14
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-ssr.md +25 -21
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-django.md +75 -55
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +3 -6
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +26 -16
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-3-6.md +8 -5
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-4.md +4 -4
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-framework.md +3 -3
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby-on-rails.md +8 -4
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-tanstack-start.md +20 -8
- package/dist/global-skills/instrument-product-analytics/references/android.md +46 -4
- package/dist/global-skills/instrument-product-analytics/references/angular.md +41 -5
- package/dist/global-skills/instrument-product-analytics/references/astro.md +41 -5
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +7 -4
- package/dist/global-skills/instrument-product-analytics/references/django.md +38 -5
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +10 -4
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/flask.md +17 -5
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +49 -4
- package/dist/global-skills/instrument-product-analytics/references/go.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +38 -7
- package/dist/global-skills/instrument-product-analytics/references/ios.md +14 -4
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +74 -8
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +39 -7
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +40 -4
- package/dist/global-skills/instrument-product-analytics/references/php.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +21 -17
- package/dist/global-skills/instrument-product-analytics/references/python.md +15 -5
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +41 -7
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +42 -6
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +31 -7
- package/dist/global-skills/instrument-product-analytics/references/usage.md +41 -4
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +42 -6
- package/dist/global-skills/manifest.json +6 -1
- package/dist/global-skills/neon/SKILL.md +235 -121
- package/dist/global-skills/neon-ai-gateway/SKILL.md +95 -16
- package/dist/global-skills/neon-functions/SKILL.md +242 -152
- package/dist/global-skills/neon-functions/references/ai-sdk.md +9 -3
- package/dist/global-skills/neon-functions/references/mastra-studio.md +1 -1
- package/dist/global-skills/neon-functions/references/mcp.md +13 -4
- package/dist/global-skills/neon-functions/references/sentry.md +165 -52
- package/dist/global-skills/neon-functions/references/sse.md +23 -6
- package/dist/global-skills/neon-object-storage/SKILL.md +40 -16
- package/dist/global-skills/neon-postgres/SKILL.md +63 -262
- package/dist/global-skills/neon-postgres-branches/SKILL.md +61 -50
- package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +22 -3
- package/dist/global-skills/resend/SKILL.md +6 -6
- package/dist/global-skills/resend/references/automations.md +2 -2
- package/dist/global-skills/resend/references/broadcasts.md +11 -3
- package/dist/global-skills/resend/references/domains.md +25 -3
- package/dist/global-skills/resend/references/installation.md +7 -7
- package/dist/global-skills/setup-payments/SKILL.md +4 -5
- package/dist/global-skills/stripe-best-practices/SKILL.md +32 -7
- package/dist/global-skills/stripe-best-practices/references/billing.md +11 -1
- package/dist/global-skills/stripe-best-practices/references/payments.md +23 -2
- package/dist/global-skills/stripe-best-practices/references/security.md +21 -11
- package/dist/global-skills/stripe-best-practices/references/tax.md +116 -11
- package/dist/global-skills/supabase/CHANGELOG.md +25 -0
- package/dist/global-skills/supabase/SKILL.md +5 -1
- package/dist/global-skills/supabase-postgres-best-practices/CHANGELOG.md +30 -0
- package/dist/global-skills/supabase-postgres-best-practices/SKILL.md +1 -1
- package/dist/global-skills/use-kit-mcp/SKILL.md +5 -5
- package/dist/global-skills/use-railway/SKILL.md +4 -4
- package/dist/global-skills/use-railway/references/iac.md +206 -57
- package/dist/global-skills/use-railway/scripts/railway-api.sh +7 -2
- package/dist/global-skills/xcode-project-setup/SKILL.md +2 -0
- package/package.json +12 -9
- package/LICENSE.md +0 -47
- package/dist/global-skills/eas-workflows/scripts/validate.js +0 -84
- package/dist/global-skills/expo-skill-feedback/scripts/skill-feedback.cjs +0 -118
- package/dist/global-skills/neon-functions/references/hono-websockets.md +0 -145
|
@@ -194,7 +194,7 @@ If you're using PostHog's JavaScript SDK on the frontend, enable tracing headers
|
|
|
194
194
|
```javascript
|
|
195
195
|
posthog.init('<ph_project_token>', {
|
|
196
196
|
api_host: 'https://us.i.posthog.com',
|
|
197
|
-
|
|
197
|
+
tracing_headers: ['your-backend-domain.com'],
|
|
198
198
|
})
|
|
199
199
|
```
|
|
200
200
|
|
|
@@ -271,6 +271,49 @@ class CoreConfig(AppConfig):
|
|
|
271
271
|
if settings.DEBUG:
|
|
272
272
|
posthog.debug = True
|
|
273
273
|
|
|
274
|
+
# Register the auth signal that identifies the login request's context.
|
|
275
|
+
from . import signals # noqa: F401
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## core/signals.py
|
|
282
|
+
|
|
283
|
+
```py
|
|
284
|
+
"""PostHog identity for the login request.
|
|
285
|
+
|
|
286
|
+
The middleware reads request.user once, before any view runs. On a login request
|
|
287
|
+
the visitor is still anonymous at that point, so the request's context has no
|
|
288
|
+
distinct ID, and calling login() inside the view does not change that. This
|
|
289
|
+
signal runs inside the login request and identifies the ambient context, so
|
|
290
|
+
every capture later in that same request is attributed to the user who just
|
|
291
|
+
logged in. Requests made after login don't need this: the middleware sees the
|
|
292
|
+
authenticated user from the start.
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
import posthog
|
|
296
|
+
from posthog import identify_context
|
|
297
|
+
from django.contrib.auth.signals import user_logged_in
|
|
298
|
+
from django.dispatch import receiver
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
@receiver(user_logged_in)
|
|
302
|
+
def identify_posthog_user(sender, request, user, **kwargs):
|
|
303
|
+
identify_context(str(user.pk))
|
|
304
|
+
|
|
305
|
+
# PII belongs in person properties, never in event properties.
|
|
306
|
+
posthog.set(
|
|
307
|
+
distinct_id=str(user.pk),
|
|
308
|
+
properties={
|
|
309
|
+
'email': user.email,
|
|
310
|
+
'username': user.username,
|
|
311
|
+
'name': user.get_full_name() or user.username,
|
|
312
|
+
'is_staff': user.is_staff,
|
|
313
|
+
'date_joined': user.date_joined.isoformat(),
|
|
314
|
+
},
|
|
315
|
+
)
|
|
316
|
+
|
|
274
317
|
```
|
|
275
318
|
|
|
276
319
|
---
|
|
@@ -739,7 +782,7 @@ urlpatterns = [
|
|
|
739
782
|
"""Django views demonstrating PostHog integration patterns"""
|
|
740
783
|
|
|
741
784
|
import posthog
|
|
742
|
-
from posthog import
|
|
785
|
+
from posthog import capture
|
|
743
786
|
from django.shortcuts import render, redirect
|
|
744
787
|
from django.contrib.auth import authenticate, login, logout
|
|
745
788
|
from django.contrib.auth.decorators import login_required
|
|
@@ -762,20 +805,11 @@ def home_view(request):
|
|
|
762
805
|
if user is not None:
|
|
763
806
|
login(request, user)
|
|
764
807
|
|
|
765
|
-
# PostHog:
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
tag('email', user.email)
|
|
771
|
-
tag('username', user.username)
|
|
772
|
-
tag('name', user.get_full_name() or user.username)
|
|
773
|
-
tag('is_staff', user.is_staff)
|
|
774
|
-
tag('date_joined', user.date_joined.isoformat())
|
|
775
|
-
|
|
776
|
-
capture('user_logged_in', properties={
|
|
777
|
-
'login_method': 'email',
|
|
778
|
-
})
|
|
808
|
+
# PostHog: the user_logged_in signal (core/signals.py) has identified
|
|
809
|
+
# this request's context, so a plain capture is attributed.
|
|
810
|
+
capture('user_logged_in', properties={
|
|
811
|
+
'login_method': 'email',
|
|
812
|
+
})
|
|
779
813
|
|
|
780
814
|
return redirect('dashboard')
|
|
781
815
|
else:
|
|
@@ -787,12 +821,9 @@ def home_view(request):
|
|
|
787
821
|
def logout_view(request):
|
|
788
822
|
"""Logout the current user"""
|
|
789
823
|
if request.user.is_authenticated:
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
with new_context():
|
|
794
|
-
identify_context(user_id)
|
|
795
|
-
capture('user_logged_out')
|
|
824
|
+
# PostHog: the middleware identified this request's context from the
|
|
825
|
+
# still-authenticated user, so capture before calling logout().
|
|
826
|
+
capture('user_logged_out')
|
|
796
827
|
|
|
797
828
|
logout(request)
|
|
798
829
|
|
|
@@ -804,12 +835,11 @@ def dashboard_view(request):
|
|
|
804
835
|
"""Dashboard page with feature flag example"""
|
|
805
836
|
user_id = str(request.user.id)
|
|
806
837
|
|
|
807
|
-
# PostHog:
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
})
|
|
838
|
+
# PostHog: the middleware already identified this request's context from the
|
|
839
|
+
# logged-in user, so a plain capture is attributed to them.
|
|
840
|
+
capture('dashboard_viewed', properties={
|
|
841
|
+
'is_staff': request.user.is_staff,
|
|
842
|
+
})
|
|
813
843
|
|
|
814
844
|
# PostHog: Check feature flag
|
|
815
845
|
show_new_feature = posthog.feature_enabled(
|
|
@@ -854,14 +884,10 @@ def consider_burrito_view(request):
|
|
|
854
884
|
count = request.session.get('burrito_count', 0) + 1
|
|
855
885
|
request.session['burrito_count'] = count
|
|
856
886
|
|
|
857
|
-
user_id = str(request.user.id)
|
|
858
|
-
|
|
859
887
|
# PostHog: Track custom event
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
'total_considerations': count,
|
|
864
|
-
})
|
|
888
|
+
capture('burrito_considered', properties={
|
|
889
|
+
'total_considerations': count,
|
|
890
|
+
})
|
|
865
891
|
|
|
866
892
|
return JsonResponse({
|
|
867
893
|
'success': True,
|
|
@@ -875,9 +901,7 @@ def profile_view(request):
|
|
|
875
901
|
user_id = str(request.user.id)
|
|
876
902
|
|
|
877
903
|
# PostHog: Track profile view
|
|
878
|
-
|
|
879
|
-
identify_context(user_id)
|
|
880
|
-
capture('profile_viewed')
|
|
904
|
+
capture('profile_viewed')
|
|
881
905
|
|
|
882
906
|
context = {
|
|
883
907
|
'user': request.user,
|
|
@@ -906,12 +930,10 @@ def trigger_error_view(request):
|
|
|
906
930
|
posthog.capture_exception(e)
|
|
907
931
|
|
|
908
932
|
# PostHog: Track error trigger event
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
'error_message': str(e),
|
|
914
|
-
})
|
|
933
|
+
capture('error_triggered', properties={
|
|
934
|
+
'error_type': error_type,
|
|
935
|
+
'error_message': str(e),
|
|
936
|
+
})
|
|
915
937
|
|
|
916
938
|
return JsonResponse({
|
|
917
939
|
'success': False,
|
|
@@ -939,17 +961,15 @@ def group_analytics_view(request):
|
|
|
939
961
|
)
|
|
940
962
|
|
|
941
963
|
# PostHog: Capture event with group
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
'
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
}
|
|
952
|
-
)
|
|
964
|
+
capture(
|
|
965
|
+
'feature_used',
|
|
966
|
+
properties={
|
|
967
|
+
'feature_name': 'group_analytics',
|
|
968
|
+
},
|
|
969
|
+
groups={
|
|
970
|
+
'company': 'acme-corp',
|
|
971
|
+
}
|
|
972
|
+
)
|
|
953
973
|
|
|
954
974
|
return JsonResponse({
|
|
955
975
|
'success': True,
|
|
@@ -446,8 +446,7 @@ class PostHogMiddleware:
|
|
|
446
446
|
|
|
447
447
|
with new_context():
|
|
448
448
|
if user:
|
|
449
|
-
identify_context(user.
|
|
450
|
-
tag("email", user.email)
|
|
449
|
+
identify_context(str(user.id))
|
|
451
450
|
tag("is_staff", user.is_staff)
|
|
452
451
|
|
|
453
452
|
await self.app(scope, receive, send)
|
|
@@ -794,12 +793,11 @@ async def login(
|
|
|
794
793
|
if user:
|
|
795
794
|
is_new_user = user.record_login(db)
|
|
796
795
|
with new_context():
|
|
797
|
-
identify_context(user.
|
|
796
|
+
identify_context(str(user.id))
|
|
798
797
|
capture(
|
|
799
798
|
"user_logged_in",
|
|
800
799
|
properties={
|
|
801
800
|
"$set": {"email": user.email, "is_staff": user.is_staff},
|
|
802
|
-
"username": user.email,
|
|
803
801
|
"is_new_user": is_new_user,
|
|
804
802
|
},
|
|
805
803
|
)
|
|
@@ -860,12 +858,11 @@ async def signup(
|
|
|
860
858
|
user = User.create_user(db, email=email, password=password, is_staff=False)
|
|
861
859
|
|
|
862
860
|
with new_context():
|
|
863
|
-
identify_context(user.
|
|
861
|
+
identify_context(str(user.id))
|
|
864
862
|
capture(
|
|
865
863
|
"user_signed_up",
|
|
866
864
|
properties={
|
|
867
865
|
"$set": {"email": user.email, "is_staff": user.is_staff},
|
|
868
|
-
"username": user.email,
|
|
869
866
|
"signup_method": "form",
|
|
870
867
|
},
|
|
871
868
|
)
|
|
@@ -265,7 +265,7 @@ def consider_burrito():
|
|
|
265
265
|
|
|
266
266
|
# PostHog: Capture custom event
|
|
267
267
|
with new_context():
|
|
268
|
-
identify_context(current_user.
|
|
268
|
+
identify_context(str(current_user.id))
|
|
269
269
|
capture("burrito_considered", properties={"total_considerations": burrito_count})
|
|
270
270
|
|
|
271
271
|
return jsonify({"success": True, "count": burrito_count})
|
|
@@ -291,7 +291,7 @@ def test_error():
|
|
|
291
291
|
if should_capture:
|
|
292
292
|
# Manually capture this specific exception in PostHog
|
|
293
293
|
with new_context():
|
|
294
|
-
identify_context(current_user.
|
|
294
|
+
identify_context(str(current_user.id))
|
|
295
295
|
event_id = posthog.capture_exception(e)
|
|
296
296
|
|
|
297
297
|
return jsonify({
|
|
@@ -398,7 +398,7 @@ from app.main import routes # noqa: E402, F401
|
|
|
398
398
|
import posthog
|
|
399
399
|
from flask import flash, redirect, render_template, request, session, url_for
|
|
400
400
|
from flask_login import current_user, login_required, login_user, logout_user
|
|
401
|
-
from posthog import capture, identify_context, new_context
|
|
401
|
+
from posthog import capture, identify_context, new_context
|
|
402
402
|
|
|
403
403
|
from app.main import main_bp
|
|
404
404
|
from app.models import User
|
|
@@ -420,12 +420,17 @@ def home():
|
|
|
420
420
|
|
|
421
421
|
# PostHog: Identify user and capture login event
|
|
422
422
|
with new_context():
|
|
423
|
-
identify_context(user.
|
|
424
|
-
|
|
425
|
-
#
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
423
|
+
identify_context(str(user.id))
|
|
424
|
+
|
|
425
|
+
# PII belongs in person properties, never in event properties
|
|
426
|
+
posthog.set(
|
|
427
|
+
distinct_id=str(user.id),
|
|
428
|
+
properties={
|
|
429
|
+
"email": user.email,
|
|
430
|
+
"is_staff": user.is_staff,
|
|
431
|
+
"date_joined": user.date_joined.isoformat(),
|
|
432
|
+
},
|
|
433
|
+
)
|
|
429
434
|
|
|
430
435
|
capture("user_logged_in", properties={"login_method": "password"})
|
|
431
436
|
|
|
@@ -464,11 +469,16 @@ def signup():
|
|
|
464
469
|
|
|
465
470
|
# PostHog: Identify new user and capture signup event
|
|
466
471
|
with new_context():
|
|
467
|
-
identify_context(user.
|
|
472
|
+
identify_context(str(user.id))
|
|
468
473
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
474
|
+
posthog.set(
|
|
475
|
+
distinct_id=str(user.id),
|
|
476
|
+
properties={
|
|
477
|
+
"email": user.email,
|
|
478
|
+
"is_staff": user.is_staff,
|
|
479
|
+
"date_joined": user.date_joined.isoformat(),
|
|
480
|
+
},
|
|
481
|
+
)
|
|
472
482
|
|
|
473
483
|
capture("user_signed_up", properties={"signup_method": "form"})
|
|
474
484
|
|
|
@@ -486,7 +496,7 @@ def logout():
|
|
|
486
496
|
"""Logout and capture event."""
|
|
487
497
|
# PostHog: Capture logout event before session ends
|
|
488
498
|
with new_context():
|
|
489
|
-
identify_context(current_user.
|
|
499
|
+
identify_context(str(current_user.id))
|
|
490
500
|
capture("user_logged_out")
|
|
491
501
|
|
|
492
502
|
logout_user()
|
|
@@ -499,7 +509,7 @@ def dashboard():
|
|
|
499
509
|
"""Dashboard with feature flag demonstration."""
|
|
500
510
|
# PostHog: Capture dashboard view
|
|
501
511
|
with new_context():
|
|
502
|
-
identify_context(current_user.
|
|
512
|
+
identify_context(str(current_user.id))
|
|
503
513
|
capture("dashboard_viewed", properties={"is_staff": current_user.is_staff})
|
|
504
514
|
|
|
505
515
|
# Check feature flag
|
|
@@ -538,7 +548,7 @@ def profile():
|
|
|
538
548
|
"""User profile page."""
|
|
539
549
|
# PostHog: Capture profile view
|
|
540
550
|
with new_context():
|
|
541
|
-
identify_context(current_user.
|
|
551
|
+
identify_context(str(current_user.id))
|
|
542
552
|
capture("profile_viewed")
|
|
543
553
|
|
|
544
554
|
return render_template("profile.html")
|
|
@@ -115,7 +115,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
115
115
|
})
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers when `
|
|
118
|
+
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers when `tracing_headers` is configured in the PostHog initialization.
|
|
119
119
|
|
|
120
120
|
**Important**: do not identify users on the server-side.
|
|
121
121
|
|
|
@@ -138,7 +138,7 @@ const handleSubmit = async () => {
|
|
|
138
138
|
}
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `
|
|
141
|
+
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `tracing_headers` option in the PostHog initialization.
|
|
142
142
|
|
|
143
143
|
**Important**: do not identify users on the server-side.
|
|
144
144
|
|
|
@@ -153,7 +153,7 @@ import { getHeader } from 'h3'
|
|
|
153
153
|
export default defineEventHandler(async (event) => {
|
|
154
154
|
const runtimeConfig = useRuntimeConfig()
|
|
155
155
|
|
|
156
|
-
// Relies on
|
|
156
|
+
// Relies on tracing_headers being set in the client-side SDK
|
|
157
157
|
const sessionId = getHeader(event, 'x-posthog-session-id')
|
|
158
158
|
const distinctId = getHeader(event, 'x-posthog-distinct-id')
|
|
159
159
|
|
|
@@ -711,6 +711,9 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
711
711
|
const posthogClient = posthog.init(runtimeConfig.public.posthog.publicKey, {
|
|
712
712
|
api_host: runtimeConfig.public.posthog.host,
|
|
713
713
|
defaults: runtimeConfig.public.posthog.posthogDefaults as any,
|
|
714
|
+
// Automatically add X-POSTHOG-SESSION-ID and X-POSTHOG-DISTINCT-ID headers
|
|
715
|
+
// to same-origin requests so server-side events join the same session.
|
|
716
|
+
tracing_headers: [window.location.hostname],
|
|
714
717
|
loaded: (posthog: PostHogInterface) => {
|
|
715
718
|
if (import.meta.env.MODE === 'development') posthog.debug()
|
|
716
719
|
},
|
|
@@ -772,7 +775,7 @@ export default defineEventHandler(async (event) => {
|
|
|
772
775
|
|
|
773
776
|
const runtimeConfig = useRuntimeConfig()
|
|
774
777
|
|
|
775
|
-
// Relies on
|
|
778
|
+
// Relies on tracing_headers being set in the client-side SDK
|
|
776
779
|
const sessionId = getHeader(event, 'x-posthog-session-id')
|
|
777
780
|
const distinctId = getHeader(event, 'x-posthog-distinct-id')
|
|
778
781
|
|
|
@@ -844,7 +847,7 @@ export default defineEventHandler(async (event) => {
|
|
|
844
847
|
|
|
845
848
|
const runtimeConfig = useRuntimeConfig()
|
|
846
849
|
|
|
847
|
-
// Relies on
|
|
850
|
+
// Relies on tracing_headers being set in the client-side SDK
|
|
848
851
|
const sessionId = getHeader(event, 'x-posthog-session-id')
|
|
849
852
|
const distinctId = getHeader(event, 'x-posthog-distinct-id')
|
|
850
853
|
|
|
@@ -117,7 +117,7 @@ export default defineNuxtConfig({
|
|
|
117
117
|
host: process.env.NUXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com',
|
|
118
118
|
clientConfig: {
|
|
119
119
|
capture_exceptions: true, // Enables automatic exception capture on the client side (Vue)
|
|
120
|
-
|
|
120
|
+
tracing_headers: ['localhost', 'yourdomain.com'], // Add your domain here
|
|
121
121
|
},
|
|
122
122
|
serverConfig: {
|
|
123
123
|
enableExceptionAutocapture: true, // Enables automatic exception capture on the server side (Nitro)
|
|
@@ -138,7 +138,7 @@ export default defineNuxtConfig({
|
|
|
138
138
|
- Client-side error tracking is enabled via `capture_exceptions: true`
|
|
139
139
|
- Server-side error tracking is enabled via `enableExceptionAutocapture: true`
|
|
140
140
|
- Source map uploads are configured for better error tracking
|
|
141
|
-
- The `
|
|
141
|
+
- The `tracing_headers` option automatically adds `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers to requests
|
|
142
142
|
|
|
143
143
|
**Important**: do not identify users on the server-side.
|
|
144
144
|
|
|
@@ -161,7 +161,7 @@ const handleSubmit = async () => {
|
|
|
161
161
|
}
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `
|
|
164
|
+
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `tracing_headers` option in the PostHog configuration.
|
|
165
165
|
|
|
166
166
|
**Important**: do not identify users on the server-side.
|
|
167
167
|
|
|
@@ -879,7 +879,7 @@ export default defineNuxtConfig({
|
|
|
879
879
|
host: process.env.NUXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com', // Optional: defaults to https://us.i.posthog.com. Use https://eu.i.posthog.com for EU region
|
|
880
880
|
clientConfig: {
|
|
881
881
|
capture_exceptions: true, // Enables automatic exception capture on the client side (Vue)
|
|
882
|
-
|
|
882
|
+
tracing_headers: [ 'localhost', 'yourdomain.com' ], // Add your domain here
|
|
883
883
|
},
|
|
884
884
|
serverConfig: {
|
|
885
885
|
enableExceptionAutocapture: true, // Enables automatic exception capture on the server side (Nitro)
|
|
@@ -84,7 +84,7 @@ import { PostHogProvider } from '@posthog/react'
|
|
|
84
84
|
posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_PROJECT_TOKEN, {
|
|
85
85
|
api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
|
|
86
86
|
defaults: '2026-01-30',
|
|
87
|
-
|
|
87
|
+
tracing_headers: [ window.location.hostname ],
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
<PostHogProvider client={posthog}>
|
|
@@ -105,7 +105,7 @@ posthog?.capture('user_logged_in', {
|
|
|
105
105
|
});
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `
|
|
108
|
+
The session and distinct ID are automatically passed to the backend via the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers because we set the `tracing_headers` option in the PostHog initialization.
|
|
109
109
|
|
|
110
110
|
**Important**: do not identify users on the server-side.
|
|
111
111
|
|
|
@@ -372,7 +372,7 @@ import { PostHogProvider } from '@posthog/react'
|
|
|
372
372
|
posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_PROJECT_TOKEN, {
|
|
373
373
|
api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
|
|
374
374
|
defaults: '2026-01-30',
|
|
375
|
-
|
|
375
|
+
tracing_headers: [ window.location.hostname ],
|
|
376
376
|
});
|
|
377
377
|
|
|
378
378
|
|
|
@@ -117,9 +117,11 @@ end
|
|
|
117
117
|
class User < ApplicationRecord
|
|
118
118
|
has_secure_password
|
|
119
119
|
|
|
120
|
-
# Called by posthog-rails for automatic user association in error reports
|
|
120
|
+
# Called by posthog-rails for automatic user association in error reports.
|
|
121
|
+
# The primary key, not the email — an email can change, which splits one
|
|
122
|
+
# person's history in two, and it is PII on every event's identity.
|
|
121
123
|
def posthog_distinct_id
|
|
122
|
-
|
|
124
|
+
id.to_s
|
|
123
125
|
end
|
|
124
126
|
|
|
125
127
|
def posthog_properties
|
|
@@ -218,7 +220,7 @@ This example includes the posthog-js snippet in the layout template to demonstra
|
|
|
218
220
|
|
|
219
221
|
1. **posthog-js** (frontend) captures pageviews, clicks, and session replay
|
|
220
222
|
2. **posthog-ruby + posthog-rails** (backend) captures business logic events, errors, and feature flag evaluations
|
|
221
|
-
3. **Shared distinct_id** — frontend and backend events are linked when the same `distinct_id` is used on both sides. Call `posthog.identify(user.
|
|
223
|
+
3. **Shared distinct_id** — frontend and backend events are linked when the same `distinct_id` is used on both sides. Call `posthog.identify(user.id.to_s)` in posthog-js after login, matching the `posthog_distinct_id` used on the backend
|
|
222
224
|
4. **Session replay** lets you watch user sessions where errors occurred
|
|
223
225
|
|
|
224
226
|
**Note:** Unlike the Django SDK, posthog-rails does not include a context middleware that reads `X-POSTHOG-SESSION-ID` or `X-POSTHOG-DISTINCT-ID` tracing headers. Frontend and backend events are correlated through the shared `distinct_id`.
|
|
@@ -584,8 +586,10 @@ class User < ApplicationRecord
|
|
|
584
586
|
# Called by posthog-rails for automatic user association in error reports.
|
|
585
587
|
# When auto_capture_exceptions and capture_user_context are enabled,
|
|
586
588
|
# posthog-rails calls this method on current_user to get the distinct_id.
|
|
589
|
+
# The primary key, not the email: an email can change, which would split one
|
|
590
|
+
# person's history in two, and it is PII on every event's identity.
|
|
587
591
|
def posthog_distinct_id
|
|
588
|
-
|
|
592
|
+
id.to_s
|
|
589
593
|
end
|
|
590
594
|
|
|
591
595
|
# Helper used by controllers when calling PostHog.identify to set person properties.
|
package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-tanstack-start.md
CHANGED
|
@@ -122,16 +122,21 @@ This client is used in API routes to track server-side events.
|
|
|
122
122
|
|
|
123
123
|
### Server-side capture (routes/api/*)
|
|
124
124
|
|
|
125
|
-
Server-side events include the client's `$session_id` so they appear in the same session in PostHog. The frontend
|
|
125
|
+
Server-side events include the client's `$session_id` so they appear in the same session in PostHog. The `tracing_headers` option on the `PostHogProvider` adds the `X-POSTHOG-SESSION-ID` and `X-POSTHOG-DISTINCT-ID` headers to same-origin requests automatically, so the frontend fetch needs no PostHog headers of its own:
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
|
-
//
|
|
128
|
+
// Client: tracing_headers is configured once on the PostHogProvider
|
|
129
|
+
options={{
|
|
130
|
+
api_host: '/ingest',
|
|
131
|
+
// ...
|
|
132
|
+
// Guarded for SSR, where `window` is undefined.
|
|
133
|
+
tracing_headers: typeof window !== 'undefined' ? [window.location.hostname] : [],
|
|
134
|
+
}}
|
|
135
|
+
|
|
136
|
+
// Frontend fetch — no manual header needed
|
|
129
137
|
await fetch('/api/burrito/consider', {
|
|
130
138
|
method: 'POST',
|
|
131
|
-
headers: {
|
|
132
|
-
'Content-Type': 'application/json',
|
|
133
|
-
'X-PostHog-Session-Id': posthog.get_session_id() ?? '',
|
|
134
|
-
},
|
|
139
|
+
headers: { 'Content-Type': 'application/json' },
|
|
135
140
|
body: JSON.stringify({ ... }),
|
|
136
141
|
})
|
|
137
142
|
```
|
|
@@ -352,11 +357,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|
|
352
357
|
password: string,
|
|
353
358
|
): Promise<boolean> => {
|
|
354
359
|
try {
|
|
360
|
+
// The session and distinct ID are added automatically by the
|
|
361
|
+
// tracing_headers option configured on the PostHogProvider.
|
|
355
362
|
const response = await fetch('/api/auth/login', {
|
|
356
363
|
method: 'POST',
|
|
357
364
|
headers: {
|
|
358
365
|
'Content-Type': 'application/json',
|
|
359
|
-
'X-PostHog-Session-Id': posthog.get_session_id() ?? '',
|
|
360
366
|
},
|
|
361
367
|
body: JSON.stringify({ username, password }),
|
|
362
368
|
})
|
|
@@ -509,6 +515,11 @@ function RootDocument({ children }: { children: React.ReactNode }) {
|
|
|
509
515
|
defaults: '2025-05-24',
|
|
510
516
|
capture_exceptions: true,
|
|
511
517
|
debug: import.meta.env.DEV,
|
|
518
|
+
// Automatically add X-POSTHOG-SESSION-ID and X-POSTHOG-DISTINCT-ID
|
|
519
|
+
// headers to same-origin requests so server-side events join the
|
|
520
|
+
// same session. Guarded for SSR, where `window` is undefined.
|
|
521
|
+
tracing_headers:
|
|
522
|
+
typeof window !== 'undefined' ? [window.location.hostname] : [],
|
|
512
523
|
}}
|
|
513
524
|
>
|
|
514
525
|
<AuthProvider>
|
|
@@ -704,11 +715,12 @@ function BurritoPage() {
|
|
|
704
715
|
setHasConsidered(true)
|
|
705
716
|
setTimeout(() => setHasConsidered(false), 2000)
|
|
706
717
|
|
|
718
|
+
// The session and distinct ID are added automatically by the
|
|
719
|
+
// tracing_headers option configured on the PostHogProvider.
|
|
707
720
|
await fetch('/api/burrito/consider', {
|
|
708
721
|
method: 'POST',
|
|
709
722
|
headers: {
|
|
710
723
|
'Content-Type': 'application/json',
|
|
711
|
-
'X-PostHog-Session-Id': posthog.get_session_id() ?? '',
|
|
712
724
|
},
|
|
713
725
|
body: JSON.stringify({
|
|
714
726
|
username: user.username,
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
> AI agents: this is one page from PostHog's docs. Full index of Markdown docs for LLMs: https://posthog.com/llms.txt
|
|
2
|
+
|
|
3
|
+
# Android - Docs
|
|
4
|
+
|
|
5
|
+
Copy page
|
|
6
|
+
|
|
1
7
|
# Android - Docs
|
|
2
8
|
|
|
3
9
|
It uses an internal queue to make calls fast and non-blocking. It also batches requests and flushes asynchronously, making it perfect to use in any part of your mobile app.
|
|
@@ -566,6 +572,41 @@ PostHog.captureFeatureView("flag-key", flagVariant = "variant-key")
|
|
|
566
572
|
PostHog.captureFeatureInteraction("flag-key", flagVariant = "variant-key")
|
|
567
573
|
```
|
|
568
574
|
|
|
575
|
+
### Bootstrapping flags
|
|
576
|
+
|
|
577
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
578
|
+
|
|
579
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping. After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
|
|
580
|
+
|
|
581
|
+
Set `config.bootstrap` before calling `setup()` to seed identity and flag values before the first `/flags` response (requires Android SDK `3.55.0`+):
|
|
582
|
+
|
|
583
|
+
Kotlin
|
|
584
|
+
|
|
585
|
+
PostHog AI
|
|
586
|
+
|
|
587
|
+
```kotlin
|
|
588
|
+
import com.posthog.PostHogBootstrapConfig
|
|
589
|
+
val config = PostHogAndroidConfig(apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST)
|
|
590
|
+
config.bootstrap = PostHogBootstrapConfig(
|
|
591
|
+
distinctId = "distinct_id_of_your_user",
|
|
592
|
+
isIdentifiedId = true,
|
|
593
|
+
featureFlags = mapOf(
|
|
594
|
+
"flag-1" to true,
|
|
595
|
+
"variant-flag" to "control"
|
|
596
|
+
)
|
|
597
|
+
)
|
|
598
|
+
PostHogAndroid.setup(this, config)
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
- **Bootstrapped identity applies during setup.** On a fresh install, setting it before `setup()` means events captured synchronously during initialization (like `Application Installed`) carry your distinct ID instead of the SDK-generated UUID.
|
|
602
|
+
- An **anonymous** bootstrap (`isIdentifiedId: false`, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the person has been identified, the SDK ignores it.
|
|
603
|
+
- An **identified** bootstrap (`isIdentifiedId: true`) is for a signed-in identity available to your app (for example, from a backend session token). On a fresh install, it seeds the distinct ID, marks the person identified, and generates a separate device ID. On a returning install, a matching anonymous ID is marked identified without emitting `$identify`; a different anonymous ID is merged via `identify()` when person profiles are enabled. This emits `$identify` unless capturing is opted out. A different, already-identified person is left untouched.
|
|
604
|
+
- **Bootstrapped flags are served until the first `/flags` response, then replaced.** A complete `/flags` response takes over entirely, so bootstrapped-only keys don't persist past it. Only *enabled* flags are seeded: a `true` boolean or a non-empty variant string. A `false` or empty value is dropped, matching posthog-js. Seed payloads with the separate `featureFlagPayloads` option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on `reset()`.
|
|
605
|
+
|
|
606
|
+
The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the `sessionID` bootstrap option. When person profiles are set to `never`, the SDK preserves a different anonymous identity instead of merging it into an identified bootstrap.
|
|
607
|
+
|
|
608
|
+
See the [SDK bootstrapping guide](/docs/libraries/bootstrapping.md) for the cross-SDK overview.
|
|
609
|
+
|
|
569
610
|
## Experiments (A/B tests)
|
|
570
611
|
|
|
571
612
|
Since [experiments](/docs/experiments/start-here.md) use feature flags, the code for running an experiment is very similar to the feature flags code:
|
|
@@ -750,6 +791,7 @@ val config = PostHogAndroidConfig(
|
|
|
750
791
|
| errorTrackingConfig | PostHogErrorTrackingConfig() | Configures error tracking. autoCapture defaults to false; set it to true to autocapture uncaught exceptions when project settings also enable error tracking. |
|
|
751
792
|
| surveys | false | Internal/experimental native Android survey support. Native Android survey UI is not fully supported or documented yet. |
|
|
752
793
|
| surveysConfig | PostHogSurveysConfig() | Internal/experimental survey display delegate configuration, primarily for hybrid SDKs. |
|
|
794
|
+
| bootstrap | null | Seeds identity (distinctId, isIdentifiedId) and feature-flag state (featureFlags, featureFlagPayloads) before the first /flags response. Bootstrapped identity applies to the first session; only enabled flags are served, until the first /flags response replaces them. See [SDK bootstrapping](/docs/libraries/bootstrapping.md#behavior-on-mobile-sdks). |
|
|
753
795
|
|
|
754
796
|
### Event filtering with `beforeSend`
|
|
755
797
|
|
|
@@ -792,6 +834,10 @@ config.addBeforeSend { event ->
|
|
|
792
834
|
}
|
|
793
835
|
```
|
|
794
836
|
|
|
837
|
+
## Push notifications
|
|
838
|
+
|
|
839
|
+
The Android SDK can register a device for [Workflows](/docs/workflows.md) push notifications and capture when a user opens one. For setup, including automatic and manual registration, capturing opens, opting out, and identity verification, see [Push notifications](/docs/workflows/push-notifications.md).
|
|
840
|
+
|
|
795
841
|
## FAQ
|
|
796
842
|
|
|
797
843
|
## What Android API level is required?
|
|
@@ -802,10 +848,6 @@ The Android SDK supports Android API 23 and newer.
|
|
|
802
848
|
|
|
803
849
|
Usually, no. The SDK declares `android.permission.INTERNET` and `android.permission.ACCESS_NETWORK_STATE`, and Android's manifest merger adds them to your app. The SDK does not declare or require an Android `Service`.
|
|
804
850
|
|
|
805
|
-
### Community questions
|
|
806
|
-
|
|
807
|
-
Ask a question
|
|
808
|
-
|
|
809
851
|
### Was this page useful?
|
|
810
852
|
|
|
811
853
|
HelpfulCould be better
|