Repository navigation
fix: gate identify on the tracking policy, and make wallet markers expire and dedup like the web SDK #95
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
fix: gate identify on the tracking policy, and make wallet markers expire and dedup like the web SDK #95
Changes from all commits
d65589e
d63009c
b4d0ba5
f795ce4
2186bee
80fbade
34592a0
238fea6
6939abe
08c81ef
414c447
1e63d27
e1eb46d
0c5f278
7806576
a6219f8
c9e0193
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -700,7 +700,14 @@ export class FormoAnalytics implements IFormoAnalytics { | |
| try { | ||
| const { userId, address, providerName, rdns } = params; | ||
| logger.info("Identify", address, userId, providerName, rdns); | ||
| if (this.hasOptedOutTracking()) return; | ||
| // The full policy, not consent alone: identify persists the user id | ||
| // and marks the wallet before trackEvent applies the chain gate, and | ||
| // a marker written on an excluded chain would silence a later | ||
| // identify on an allowed one. | ||
| if (!this.shouldTrack()) { | ||
| logger.info("identify() skipped: tracking is suppressed for this visitor or chain"); | ||
| return; | ||
| } | ||
|
|
||
| let validAddress: Address | undefined = undefined; | ||
| if (address) { | ||
|
|
@@ -723,26 +730,21 @@ export class FormoAnalytics implements IFormoAnalytics { | |
| storage().set(SESSION_USER_ID_KEY, userId); | ||
| } | ||
|
|
||
| // Check for duplicate identify | ||
| const isAlreadyIdentified = validAddress | ||
| ? this.session.isWalletIdentified(validAddress, rdns || "") | ||
| : false; | ||
|
|
||
| if (isAlreadyIdentified) { | ||
| logger.info( | ||
| `Identify: Wallet ${providerName || "Unknown"} with address ${validAddress} already identified` | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| // Mark as identified | ||
| // Dedup on the effective user, as the wire event carries it, not only | ||
| // the argument: a re-identify that changes the user is sent again. | ||
| if (validAddress) { | ||
| this.session.markWalletIdentified(validAddress, rdns || ""); | ||
| if (this.session.isWalletIdentified(validAddress, rdns || "", this.currentUserId, properties)) { | ||
| logger.info( | ||
| `Identify: Wallet ${providerName || "Unknown"} with address ${validAddress} already identified` | ||
| ); | ||
| return; | ||
| } | ||
| this.session.markWalletIdentified(validAddress, rdns || "", this.currentUserId, properties); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the same wallet-user is identified with Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not changed. A profile that goes free, pro, free inside one minute meets the rolling duplicate window, which the two SDKs share and which was reviewed and kept as is (dedup design items were explicitly left out of this round). The marker records what the SDK accepted at the session level; the queue window is a separate, documented layer. |
||
| } | ||
|
|
||
| await this.trackEvent( | ||
| EventType.IDENTIFY, | ||
| { address: validAddress, providerName, userId, rdns }, | ||
| { address: validAddress, providerName, userId: this.currentUserId, rdns }, | ||
| properties, | ||
| context, | ||
| callback | ||
|
|
@@ -764,7 +766,7 @@ export class FormoAnalytics implements IFormoAnalytics { | |
| // The full policy, not consent alone: a detect refused by the chain gate | ||
| // after the marker is written would silence the wallet for the session. | ||
| if (!this.shouldTrack()) { | ||
| logger.info("detect() skipped: tracking is suppressed for this wallet or chain"); | ||
| logger.info("detect() skipped: tracking is suppressed for this visitor or chain"); | ||
| return; | ||
| } | ||
| if (this.session.isWalletDetected(rdns)) { | ||
|
|
||
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.
When
identify()omitsuserIdafter a user was restored from storage or set by an earlier call, this checks and writes the marker underthis.currentUserId, but the payload at line 747 still contains the undefined argument. Fresh evidence against the earlier thread's premise is thatEventFactory.create()passesevent.userIddirectly togenerateIdentifyEvent()(EventFactory.ts:815-821), which writes it touser_id, so the separate current-user argument passed toEventManagerdoes not reach the identify event. The resulting anonymous identify is marked as though it belonged to the current user, and a later explicit identify for that user is suppressed; pass the same effective user ID in the identify payload.Useful? React with 👍 / 👎.
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.
Fixed in 7806576: the identify payload carries the effective user id, the same value the marker is keyed on. Test: "identify() without a user id carries the effective user on the wire, as the marker does".