Skip to content

feat(analytics-controller): add optional invocation options for track, identify, view#8701

Open
gauthierpetetin wants to merge 4 commits into
mainfrom
feat/analytics-invocation-options
Open

feat(analytics-controller): add optional invocation options for track, identify, view#8701
gauthierpetetin wants to merge 4 commits into
mainfrom
feat/analytics-invocation-options

Conversation

@gauthierpetetin
Copy link
Copy Markdown
Contributor

@gauthierpetetin gauthierpetetin commented May 5, 2026

Explanation

Add the possibility to forward context, callback, messageId, and timestamp to AnalyticsController for trackEvent, identify, and trackView functions, , as this is needed in Extension.

References

NA

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Extends the public AnalyticsPlatformAdapter and controller method signatures, which is potentially breaking for downstream adapter implementations and callers. Logic change also alters messageId for split anonymous events, which could affect event deduping/tracing semantics.

Overview
Adds optional AnalyticsInvocationOptions (context, callback, messageId, timestamp) and threads it through AnalyticsController.trackEvent, identify, and trackView into AnalyticsPlatformAdapter.track/identify/view.

When anonymous-event splitting is enabled and sensitive properties are present, the controller now derives a distinct messageId suffix for the anonymous/combined track call to avoid SDK deduping, and the test suite + changelog are updated accordingly.

Reviewed by Cursor Bugbot for commit 20a4e85. Bugbot is set up for automated code reviews on this repo. Configure here.

…, identify, view

Forward AnalyticsInvocationOptions (context, callback, messageId, timestamp)
from AnalyticsController to AnalyticsPlatformAdapter for trackEvent,
identify, and trackView. Extend adapter method signatures with optional
third argument. Export AnalyticsContext and AnalyticsInvocationCallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gauthierpetetin gauthierpetetin force-pushed the feat/analytics-invocation-options branch from 7a3f783 to 002a571 Compare May 11, 2026 11:06
@gauthierpetetin gauthierpetetin marked this pull request as ready for review May 11, 2026 11:33
@gauthierpetetin gauthierpetetin requested review from a team as code owners May 11, 2026 11:33
/**
* Optional context object attached to the invocation.
*/
context?: AnalyticsContext;
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.

Q: there's already a context attached by Segment SDK, how does this interfere with it?

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.

Extension adds context to events, that Segment SDK doesn't provide (cf. this code).
Segment can still add its own SDK context. We are not replacing that.
We are allowing the adapter to pass additional context through to Segment. If there are key collisions, that is a platform-adapter concern, so Extension should avoid overriding SDK-owned fields unless intentional.
So far, the only SDK-owned fields are:

context.library.name = '@segment/analytics-node'
context.library.version = <package version>

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.

Will all these values be in the same context object in the final event payload?

/**
* Optional callback when the invocation completes or fails.
*/
callback?: AnalyticsInvocationCallback;
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.

Q: What are the use cases of this? The tracking should never block or interfere with UX, so it's best effort and errors are handled inside controller, right?

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.

See message here.

Also callback is not for UX and should not be awaited by product flows. It is only the cleanup signal: once Segment finishes processing the call, we remove that messageId from the persisted queue.

/**
* Optional stable identifier for deduplication or tracing.
*/
messageId?: string;
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.

Q; we already have a message ID in the Segment payload. How is this different?

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.

See message here.

We need a messageId that is defined by MetaMetricsController before sending the event to Segment, in order to persist the event queue.

/**
* Optional event time. ISO strings, Unix timestamps in milliseconds, or Date values are typical.
*/
timestamp?: Date | number | string;
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.

Q: we already have a timestamp in Segment payload. How is this different?

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.

We need a timestamp that is defined by MetaMetricsController before sending the event to Segment, in order to preserve the original event time when the event is replayed later, thanks to the persisted event queue.

@gauthierpetetin
Copy link
Copy Markdown
Contributor Author

@NicolasMassart the reason why we need to pass callback, messageId, and timestamp is because we need them to implement a persisted event queue.

On Mobile, that’s achieved thanks to Segment SDK’s storePersistor option, but unfortunately there’s no equivalent option in the Segment SDK used by Extension.

That's quite problematic by the way, because it prevents us from fully getting rid of the existing MetaMetricController: we still need it besides AnalyticsController in order to persist the event queue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants