Skip to content

fix(capture): one property precedence for client SDKs - #143

Merged
turnipdabeets merged 4 commits into
mainfrom
fix/client-property-precedence-simple
Oct 27, 2026
Merged

turnipdabeets merged 4 commits into
mainfrom
fix/client-property-precedence-simple

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #114. That PR let the caller's event properties win over registered and SDK context properties, but kept exceptions: the SDK SHALL set $is_identified and $process_person_profile after the caller's properties, and MAY do the same for $session_id/$window_id, the session replay debug properties, $geoip_disable and posthog-js bookkeeping. SDKs answer the MAY items differently, so the order is hard to predict.

This replaces the exceptions with one order for client SDKs, each layer overwriting the one before:

  1. Properties the SDK sets itself
  2. Registered (super) properties
  3. The properties the caller passes on the event
  4. before_send

Changes

  • Caller-supplied event properties take precedence states the four layers and drops the SHALL/MAY list, so no key is called out as an exception.
  • Scenarios, in the spec and in acceptance/public/capture.feature:
    • new: "Registered property overrides an SDK-set property"
    • "Caller can't override person-processing state" becomes "Caller property overrides an SDK-set property"
  • Capture's Behavior step 4 lists the client layers to match.
  • Server SDKs are unchanged.

openspec validate --specs --strict passes (67/67). The scenarios reuse existing steps.

Impact

  • posthog-ios: conforms in 4.0 (feat!: send events through capture v1 and add captureAi posthog-ios#938).
  • posthog-js (browser): already merges super properties over its SDK properties; needs $is_identified, $process_person_profile, the session properties, the replay debug properties and page/session bookkeeping set before super and caller properties instead of after.
  • posthog-android: merges registered properties before SDK context, so SDK context wins today; needs the same reorder.
  • @posthog/core (react-native, js-lite): sets $geoip_disable and person-processing state after the caller's properties; needs the same reorder.
  • posthog-flutter: follows the native SDK.

🤖 Generated with Claude Code

… before_send

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@turnipdabeets
turnipdabeets requested a review from a team as a code owner October 23, 2026 17:58
turnipdabeets and others added 2 commits October 23, 2026 13:59
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@turnipdabeets turnipdabeets changed the title fix(capture): one property precedence for client SDKs: global, event, before_send fix(capture): one property precedence for client SDKs Oct 23, 2026
### Requirement: Caller-supplied event properties take precedence

On client SDKs, a property the caller passes on an event SHALL win over a registered (super) property with the same key and over an SDK context property with the same key, such as `$lib`, `$lib_version`, `$os`, `$app_version`, `$screen_width`, `$current_url`, `$screen_name`, `$feature/<key>` or `$active_feature_flags`. A group the caller passes for the event SHALL win over a registered group of the same type.
On client SDKs, an event's properties SHALL be merged in this order, each layer overwriting the one before:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 An AI agent wrote this on behalf of @ioannisj.

posthog-js sets $process_person_profile last on purpose (packages/browser/src/posthog-core.ts:2331 says "so it cannot be overridden"). @posthog/core and android do the same today.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a discussion in the v1 thread and localed a change to the override behavior for these. global/super props can now be overridden by end users per-event and on before_send in v1 SDKs. This is documented in the draft public docs PR for release and per-SDK migration guides too as needed.

Comment thread openspec/specs/capture/spec.md
Comment thread openspec/specs/capture/spec.md
Comment thread openspec/changes/archive/2026-10-23-simplify-event-property-precedence/tasks.md Outdated
…he layers

Say a registered or caller value for an SDK-set key changes that event only, keep the project token as request routing, and align the layer count across proposal, tasks and spec.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets merged commit f60b28d into main Oct 27, 2026
7 checks passed
@turnipdabeets
turnipdabeets deleted the fix/client-property-precedence-simple branch October 27, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants