Skip to content

feat: add an Objective-C setter for the wrapper SDK name and version - #1027

Merged
turnipdabeets merged 1 commit into
chore/v4-remove-deprecatedfrom
feat/v4-objc-sdk-name
Nov 5, 2026
Merged

turnipdabeets merged 1 commit into
chore/v4-remove-deprecatedfrom
feat/v4-objc-sdk-name

Conversation

@turnipdabeets

Copy link
Copy Markdown
Contributor

Public API change: none. Adds PostHogSDK.setSdkName(_:version:) behind @_spi(PostHogInternal), next to the postHogSdkName/postHogVersion globals it sets.

💡 Motivation and Context

Capture v1 (#938) drops $lib/$lib_version from event properties and reads the SDK name and version from the PostHog-Sdk-Info header, built from postHogSdkName/postHogVersion. Those are Swift globals, so they aren't in the Objective-C header. Kotlin Multiplatform calls posthog-ios through that header, so it can't set them. Today it stamps $lib in beforeSend, and capture v1 strips that out. Without this setter, every KMP Apple event on 4.0 reports as posthog-ios.

  • @objc(setSdkName:version:) is a class method in a PostHogSDK extension. The generated PostHog-Swift.h includes it, @_spi included, the same way PostHogSessionManager is already exposed. Swift wrappers (Flutter) keep assigning the globals directly.
  • Wrappers must call it before setup. PostHogContext caches $lib for person properties the first time it reads it.

KMP adopts it in PostHog/posthog-kmp#108.

💚 How did you test it?

  • New Swift Testing case in PostHogApiTest: PostHogSDK responds to setSdkName:version: from the ObjC runtime, and a request sent afterwards has User-Agent: posthog-kmp/1.2.3. Dropping the @objc makes it fail.
  • make test filter=PostHogApiTest: 65 tests pass. make lint passes (warnings only).
  • End to end with feat!: send events through capture v1 and add captureAi #938 cherry-picked on top: built posthog-kmp against that checkout and ran it on an iOS 27.2 simulator and on macOS against a local stub server. /i/v1/analytics/events received PostHog-Sdk-Info: posthog-kmp/0.10.0, with no $lib in the body.
  • Not run: full make test, make apiCheck (xcpretty isn't installed locally; the setter is SPI, so the public API snapshots shouldn't change), and the Xcode-scheme iOS simulator tests: the test runner hung before connecting on this machine.

📝 Checklist

  • All commits are signed (see Commit signing)
  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file (added to .changeset/v4-major-release.md, where this branch folds 4.0 changes)

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Claude Code (Claude Opus 5.5) wrote the setter while preparing KMP for posthog-ios 4.0. Before writing it, I checked that an @_spi @objc member still appears in the generated ObjC header, so it could stay wrapper-only instead of becoming public API. The setter targets the 4.0 branch rather than #938 because it only touches the existing globals.

🤖 Generated with Claude Code

Kotlin Multiplatform calls posthog-ios through its Objective-C header, so it
can't assign the Swift-only `postHogSdkName`/`postHogVersion` globals. With
capture v1 dropping `$lib` from event properties, every KMP Apple event would
report as posthog-ios.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets turnipdabeets self-assigned this Nov 4, 2026
turnipdabeets added a commit to PostHog/posthog-kmp that referenced this pull request Nov 4, 2026
Capture v1 strips `$lib`/`$lib_version` from event properties and reads them
from the PostHog-Sdk-Info header, so the `$lib` stamping in beforeSend no
longer reaches PostHog. Set the native SDK name and version before setup
instead (PostHog/posthog-ios#1027), drop the stamping, and only install the
native beforeSend when the app configures callbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets marked this pull request as ready for review November 4, 2026 20:32
@turnipdabeets
turnipdabeets requested a review from a team as a code owner November 4, 2026 20:32
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-11-04T20:45:48.515825+00:00
Duration: 239603ms

⚠️ Some Tests Failed

46/47 tests passed, 1 failed


Capture Tests

⚠️ 29/30 tests passed, 1 failed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 2919ms
Format Validation.Event Has Uuid ✅ 2833ms
Format Validation.Event Has Lib Properties ✅ 2834ms
Format Validation.Distinct Id Is String ✅ 2926ms
Format Validation.Token Is Present ✅ 427ms
Format Validation.Custom Properties Preserved ✅ 2943ms
Format Validation.Event Has Timestamp ✅ 2951ms
Format Validation.Non Utc Event Timestamp Is Converted To Utc ✅ 2784ms
Retry Behavior.Retries On 503 ✅ 11754ms
Retry Behavior.Does Not Retry On 400 ✅ 4798ms
Retry Behavior.Does Not Retry On 401 ✅ 4814ms
Retry Behavior.Respects Retry After Header ✅ 7918ms
Retry Behavior.Implements Backoff ✅ 21789ms
Retry Behavior.Retries On 500 ✅ 9272ms
Retry Behavior.Retries On 502 ✅ 8934ms
Retry Behavior.Retries On 504 ✅ 9341ms
Retry Behavior.Max Retries Respected ❌ 21707ms
Deduplication.Generates Unique Uuids ✅ 2922ms
Deduplication.Preserves Uuid On Retry ✅ 9233ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 16296ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 7930ms
Deduplication.No Duplicate Events In Batch ✅ 3038ms
Deduplication.Different Events Have Different Uuids ✅ 2966ms
Compression.Sends Gzip When Enabled ✅ 441ms
Batch Format.Uses Proper Batch Structure ✅ 2859ms
Batch Format.Flush With No Events Sends Nothing ✅ 352ms
Batch Format.Multiple Events Batched Together ✅ 3006ms
Error Handling.Does Not Retry On 403 ✅ 4870ms
Error Handling.Does Not Retry On 413 ✅ 4838ms
Error Handling.Retries On 408 ✅ 9310ms

Failures

retry_behavior.max_retries_respected

Expected 4 requests, got 6

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 2819ms
Request Payload.Flags Request Uses V2 Query Param ✅ 2833ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 2829ms
Request Payload.Flags Request Omits Authorization Header ✅ 2742ms
Request Payload.Token In Flags Body Matches Init ✅ 2787ms
Request Payload.Groups Round Trip ✅ 2734ms
Request Payload.Groups Default To Empty Object ✅ 3138ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 2791ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 2864ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 2708ms
Request Lifecycle.No Flags Request On Init Alone ✅ 111ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 2834ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 5489ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 2811ms
Retry Behavior.Retries Flags On 502 ✅ 2963ms
Retry Behavior.Retries Flags On 504 ✅ 2857ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 2964ms

}
let request = try #require(server.batchRequests.first)
#expect(request.value(forHTTPHeaderField: "User-Agent") == "posthog-kmp/1.2.3")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Once this meets the capture v1 branch, could the test also check the PostHog-Sdk-Info header? That's the one PostHog reads for the SDK name.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will add this to #938 since this doesnt target that branch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added on #938 in 4d22167.

@ioannisj ioannisj left a comment

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.

No findings. I checked the setter against the generated PostHog-Swift.h and the public API snapshot, and it's in the header and stays out of the snapshot, as the description says.

@turnipdabeets
turnipdabeets merged commit 2247e6f into chore/v4-remove-deprecated Nov 5, 2026
48 checks passed
@turnipdabeets
turnipdabeets deleted the feat/v4-objc-sdk-name branch November 5, 2026 14:50
turnipdabeets added a commit that referenced this pull request Nov 5, 2026
PostHogApi.batch is captureV1 on this branch, so the setSdkName test from #1027 sends through it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets turnipdabeets mentioned this pull request Nov 5, 2026
6 of 18 tasks
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