-
Notifications
You must be signed in to change notification settings - Fork 412
Include attribution data in POST /receipt when using SK2 in Observer mode #6233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ajpallares
merged 17 commits into
main
from
pallares/send-paywall-data-in-sk2-observer-mode
Feb 9, 2026
Merged
Include attribution data in POST /receipt when using SK2 in Observer mode #6233
ajpallares
merged 17 commits into
main
from
pallares/send-paywall-data-in-sk2-observer-mode
Feb 9, 2026
+422
−10
Conversation
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
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
# Conflicts: # Sources/Purchasing/Purchases/PurchasesOrchestrator.swift
Contributor
Author
|
@RCGitBot please test |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
tonidero
approved these changes
Feb 9, 2026
Contributor
tonidero
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great as always 💪 !
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.
Checklist
purchases-androidand hybridsMotivation
The SK2 transaction listener delegate (
storeKit2TransactionListener(_:updatedTransaction:)) was not includingpresentedOfferingContextorpresentedPaywallin thePurchasedTransactionDatasent to POST /receipt. This meant paywall attribution data was lost for:.purchasesAreCompletedBy: .myApp)Transaction.updates, not the SDK's purchase flowNote that the
presentedOfferingContextwas already being cached for StoreView purchases viaonInAppPurchaseStartinPaywallExtensions.swift, but was never retrieved by the SK2 transaction listener — so these purchases were missing offering attribution even in non-observer mode.Description
presentedOfferingContextandpresentedPaywallbefore posting the receipt, matching the behavior of the SK1 flow.TransactionReasonenum (.purchase,.renewal) that mirrors StoreKit 2'sTransaction.Reason(iOS 17+). When the reason is not available (SK2 on iOS < 17), it isnil. This is used to skip attribution for known renewals, avoiding false positives.Note on duplicate receipt posts in observer mode
In observer mode (i.e. when
purchasesAreCompletedBy: .myApp), a purchase can potentially be made through the SDK'spurchasemethod. Although this is considered a faulty integration of the SDK, the SDK does not prevent this in any way. In this case, the POST /receipt after apurchasewill be called twice for the same transaction:Transaction.updates): contains the attribution data (presentedOfferingContext,presentedPaywall) but withsdk_originated = false.purchasemethod itself: contains no attribution data (already consumed by the listener) but withsdk_originated = true.This is expected and confirmed with the backend team — the backend will use the first POST because it contains the attribution data.