feat(mobile): attach device info to every PostHog event - #4885
Merged
Conversation
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the Notes and assumptions
Files Reviewed (5 files)
Reviewed by claude-opus-5 · Input: 34 · Output: 12.9K · Cached: 896.7K Review guidance: REVIEW.md from base branch |
iscekic
enabled auto-merge (squash)
July 30, 2026 12:13
pandemicsyn
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every PostHog event from the mobile app now carries device metadata automatically — no call-site changes, no duplicated properties.
What: installs
expo-device(~57.0.1) and adds onedevice_form_factorproperty via PostHog'scustomAppPropertiesconstructor option.Why: product analytics needs manufacturer, model, OS name/version, device type, and emulator-vs-device segmentation on mobile events.
How: posthog-react-native 4.59.0 ships an optional
expo-deviceintegration (dist/optional/OptionalExpoDevice.js, a try/catchrequire). Verified against the installed SDK source (dist/native-deps.jsgetAppProperties()): installingexpo-devicealone turns on auto-capture of$device_manufacturer,$device_name(marketing model name),$os_name,$os_version,$is_emulatoron every event. Already captured before this change:$device_type(always the string'Mobile'— no phone/tablet granularity),$app_name/$app_version/$app_build/$app_namespace,$locale/$timezone,$screen_width/$screen_height.The one real gap is form factor, so this PR adds
device_form_factor('phone' | 'tablet' | 'desktop' | 'tv' | 'unknown'— a total mapping ofDevice.DeviceType+null, always present).Decisions:
customAppProperties, notclient.register— registered super properties are cleared byclient.reset()on logout and memoized init never re-registers;_appProperties(wherecustomAppPropertiesmerges) survive reset and land on every event including the first, synchronously.$device_typeoverride — it's reserved SDK vocabulary; we add a plainly-named property instead.Device.brandis a near-duplicate of$device_manufacturerwith no extra segmentation value (YAGNI).setDefaultPersonPropertiesalready feeds flag evaluation; form-factor flag targeting is not a stated need.Pre-existing observation (not fixed here, out of scope): the existing
client.register({ platform: 'mobile' })super property has the same reset gap — afterresetAnalyticsUser()on logout,platformis gone until the app restarts. That behavior predates this PR and is unchanged.Verification
No manual runtime testing — E2E is skipped as inert: analytics is disabled in every locally buildable configuration (
disabled: __DEV__ininitPostHog), so dev builds send no events and there is no observable runtime surface on simulator/emulator. Verification is unit tests plus the pinned SDK source contract.apps/mobile/src/lib/analytics/posthog.test.ts): totaldevice_form_factorenum mapping over everyDeviceType+ null; auto-captured properties preserved (spread, not replaced);platform: 'mobile'registration unchanged; init memoization unchangedexpo-device@57.0.1resolvable from posthog-react-native's package context (the SDK's optionalrequire('expo-device')resolves;expo-deviceis a declared optional peer>= 4.0.0)pnpm format,pnpm typecheck,pnpm lint,pnpm check:unused,pnpm testfromapps/mobile/— all pass (288 files / 2466 tests)pnpx expo-doctorbefore/after — byte-identical output; the 13 version mismatches below are pre-existing onmainand intentionally not fixed hereexpo-doctor output (before = after, pre-existing on main)
Note:
expo-deviceis a native module — a new EAS dev-client build is required before the app runs with it.Visual Changes
N/A
Reviewer Notes
$device_name(marketing name like "iPhone 12");$device_modelis not populated on the expo-device path.