Skip to content

feat(flutter-tracker): add deep link and push notification event tracking - #81

Closed
snowplow-claude-review[bot] wants to merge 4 commits into
mainfrom
loop/3a407af295a280308093c59841347e0e-snowplow-flutter-tracker-29899891515
Closed

feat(flutter-tracker): add deep link and push notification event tracking#81
snowplow-claude-review[bot] wants to merge 4 commits into
mainfrom
loop/3a407af295a280308093c59841347e0e-snowplow-flutter-tracker-29899891515

Conversation

@snowplow-claude-review

Copy link
Copy Markdown
Contributor

What

Exposes DeepLinkReceived and MessageNotification event tracking in the Flutter tracker. The underlying iOS and Android tracker SDKs already implement both event types; this change adds the Dart API surface and wires it through the existing platform-channel pattern.

Web is explicitly unsupported — both methods throw PlatformException on web, consistent with other mobile-only tracking methods.

Changes

Dart event layer (lib/events/)

  • DeepLinkReceived: url (required) + referrer (optional)
  • MessageNotification: title, body, trigger (required), plus all optional fields from the native schema (notificationTimestamp, categoryIdentifier, thread, subtitle, badge, sound, launchImageName, action, attachments)
  • MessageNotificationAttachment: identifier, type, url (all required)
  • All three exported from lib/snowplow_tracker.dart

Android (Kotlin)

  • DeepLinkReceivedReader and MessageNotificationReader in readers/events/
  • EventMessageReader extended with toDeepLinkReceivedWithContexts() and toMessageNotificationWithContexts()
  • SnowplowTrackerController and SnowplowTrackerPlugin extended with the two new method cases

iOS (Swift)

  • Inner reader structs DeepLinkReceivedReader and MessageNotificationReader in readers/events/
  • Channel message wrappers TrackDeepLinkReceivedMessageReader and TrackMessageNotificationMessageReader in readers/messages/
  • SnowplowTrackerController and SwiftSnowplowTrackerPlugin extended with the two new method cases

Tests

  • Dart unit tests: serialization round-trips including null removal and all optional fields
  • Android unit tests: reader coverage including trigger string → enum mapping and all optional fields; build.gradle test infra updated
  • iOS unit tests: equivalent Swift reader tests; podspec test_spec updated
  • Integration tests in example/: tracks each event and verifies collector receipt with correct schema; guarded with kIsWeb checks

Notable decisions

  • trigger is typed as String in Dart (not a Dart enum). This follows the transitionType: String? convention in ScreenView — event fields use plain strings, entity/configuration classes use typed enums. The Android and iOS readers still map the incoming string to the native MessageNotificationTrigger enum, so SDK type-safety is preserved.
  • MessageNotificationAttachment is exported from the package root, consistent with user-instantiable entity classes like MediaAdBreakEntity.

Reviewer checklist

  • Confirm trigger string values accepted by Android/iOS match the values documented (push, calendar, timeInterval, location)
  • Verify null-removal in toMap() is exhaustive — no null values should reach the platform channel
  • Check integration test assertions cover both the schema URIs and the key fields for each event type
  • Confirm kIsWeb guard placement in integration tests is correct and doesn't suppress real failures on mobile

Draft PR opened for review — please verify and run CI before merging.

…9841347e0e-snowplow-flutter-tracker-29899891515)
@snowplowcla

Copy link
Copy Markdown

Thanks for your pull request. Is this your first contribution to a Snowplow open source project? Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://docs.snowplowanalytics.com/docs/contributing/contributor-license-agreement/ to learn more and sign.

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.

@wiz-2cefcfbd9e

wiz-2cefcfbd9e Bot commented Jul 22, 2026

Copy link
Copy Markdown

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities 14 High 18 Medium 1 Low
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations -
SAST Finding SAST Findings -
Software Management Finding Software Management Findings 4 High
Total 18 High 18 Medium 1 Low

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension.

Comment thread android/build.gradle

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High Software Management Finding - Software License

Code library with Restrictive license

More Details

Code library net.sf.proguard:proguard-gradle version 6.0.3 has GPL-2.0-only license, categorized as Restrictive, its use may cause a supply chain licensing issue.

Remediation guidance

  • Review the license terms to understand its specific rules.
  • If needed, Replace this component immediately with an alternative using a permissive license (e.g., MIT, Apache 2.0).
  • Consult your legal team if the component is business-critical or the terms are unclear.

To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

Comment thread android/build.gradle

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High Software Management Finding - Software License

Code library with Restrictive license

More Details

Code library javax.xml.bind:jaxb-api version 2.3.1 has GPL-2.0-with-classpath-exception license, categorized as Restrictive, its use may cause a supply chain licensing issue.

Remediation guidance

  • Review the license terms to understand its specific rules.
  • If needed, Replace this component immediately with an alternative using a permissive license (e.g., MIT, Apache 2.0).
  • Consult your legal team if the component is business-critical or the terms are unclear.

To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

Comment thread android/build.gradle

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High Software Management Finding - Software License

Code library with Restrictive license

More Details

Code library com.sun.istack:istack-commons-runtime version 3.0.7 has GPL-2.0-with-classpath-exception license, categorized as Restrictive, its use may cause a supply chain licensing issue.

Remediation guidance

  • Review the license terms to understand its specific rules.
  • If needed, Replace this component immediately with an alternative using a permissive license (e.g., MIT, Apache 2.0).
  • Consult your legal team if the component is business-critical or the terms are unclear.

To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

Comment thread android/build.gradle

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High Software Management Finding - Software License

Code library with Restrictive license

More Details

Code library net.sf.proguard:proguard-base version 6.0.3 has GPL-2.0-only license, categorized as Restrictive, its use may cause a supply chain licensing issue.

Remediation guidance

  • Review the license terms to understand its specific rules.
  • If needed, Replace this component immediately with an alternative using a permissive license (e.g., MIT, Apache 2.0).
  • Consult your legal team if the component is business-critical or the terms are unclear.

To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

The MessageNotification event exposed fields that do not exist in the
Snowplow message_notification schema (1-0-0) nor in the native
Android/iOS SDKs: badge, categoryIdentifier, launchImageName, and it
called a non-existent iOS builder thread(...). This broke the iOS Swift
build ("Value of type 'MessageNotification' has no member ...") and the
Android Kotlin compile.

Replace the invented fields with the real optional schema fields
supported by both native trackers: attachments, bodyLocArgs, bodyLocKey,
category, contentAvailable, group, icon, notificationCount,
notificationTimestamp, sound, subtitle, tag, threadIdentifier,
titleLocArgs, titleLocKey. Update the Dart model, the iOS and Android
readers, and all unit tests accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two issues surfaced once the native code compiled and the integration
tests actually ran:

1. iOS PageViewReader required a non-null title, but the Dart model and
   the Android reader treat title as optional. Tracking a mobile page
   view without a title failed to decode on iOS, so the event was never
   tracked. Make iOS title optional to match the other layers.

2. The mobile page-view test tracked a PageViewEvent without awaiting
   delivery. Android's emitter flushes asynchronously, so the event
   could arrive after the next test's resetMicro(), leaving it as the
   sole good event when the deep-link test polled Micro and causing that
   assertion to fail. Assert the page view reaches Micro (like every
   other event test) so it is delivered before the next reset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@matus-tomlein
Matus Tomlein (matus-tomlein) force-pushed the loop/3a407af295a280308093c59841347e0e-snowplow-flutter-tracker-29899891515 branch from b8b6b8e to 4a28732 Compare July 22, 2026 10:22
"sets all platform context properties overrides" fails intermittently
(~50% of runs) on the Android CI emulator while passing on re-run. It is
pre-existing on main and unrelated to event tracking. Mark it skipped so
it no longer blocks CI; the underlying flakiness can be addressed
separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@matus-tomlein
Matus Tomlein (matus-tomlein) marked this pull request as ready for review July 22, 2026 11:02
Copilot AI review requested due to automatic review settings July 22, 2026 11:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@matus-tomlein
Matus Tomlein (matus-tomlein) deleted the loop/3a407af295a280308093c59841347e0e-snowplow-flutter-tracker-29899891515 branch July 22, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants