Tracking search analytics events in mobile apps
Learn how to use Activity Flow listeners and hooks to track Intelligent Search analytics events in Flutter and React Native apps.
In this guide, you will learn how to add tracking to search screens in Flutter and React Native apps so that Activity Flow can capture Intelligent Search analytics events: impressions and clicks on search results and autocomplete suggestions.
The Activity Flow click, view, and impression listeners accept a metadata map with free-form parameters. The elementSource key identifies the origin of the event and is sent at the top level of the payload, while the remaining keys in the map become extra parameters inside attributes.
Before you begin
This guide assumes the Activity Flow SDK is already installed in your app. If you haven't set it up yet, see Installing Activity Flow in Flutter apps or Installing Activity Flow in React Native apps.
Understanding the tracking parameters
elementSource must be one of the following values:
| Value | Screen |
|---|---|
search-result | Search results gallery, including the no-results search screen |
search-autocomplete | Autocomplete product suggestions |
Extra parameters:
| Parameter | Required | Description |
|---|---|---|
searchId | Yes, in every event | The search identifier, returned by the Intelligent Search response itself. |
productId | Yes, on click | The ID of the clicked product. |
productPosition | Yes, on click | The product's position in the list, 1-based, absolute across pages. |
productSpecification | No | The product's specification value, when the API returns it. |
searchIdis generated by Intelligent Search and returned in the search response (product_searchon the results gallery,product_suggestionson autocomplete). Never create, derive, or reuse this value.
Tracking the results gallery
Follow the steps below to track impressions and clicks on the search results gallery, including the no-results screen.
-
Add the impression and click listeners for your platform. If
searchIddidn't come back in the response or is empty, don't add the listeners or send the event: it's better to lose the event than to record one that can't be attributed to a search.Flutter
_11resultList.addImpressionListener({_11'elementSource': 'search-result',_11'searchId': searchId,_11});_11_11productCard.addClickListener({_11'elementSource': 'search-result',_11'searchId': searchId,_11'productId': product.productId,_11'productPosition': (positionOffset + index + 1).toString(),_11});React Native
_11useImpressionObserver({_11elementSource: 'search-result',_11searchId,_11});_11_11const { afHandlePress } = useClickObserver({_11elementSource: 'search-result',_11searchId,_11productId: product.productId,_11productPosition: String(positionOffset + index + 1),_11}); -
Apply the same impression listener to the no-results screen's container, since a search without results still counts as exactly one impression.
On Flutter,
addImpressionListenerre-fires when the metadata map changes, so each newsearchIdautomatically generates a new impression.
Tracking autocomplete
Autocomplete follows the same pattern as the results gallery, but with its own elementSource value and searchId.
-
Use the same listeners with
elementSource: 'search-result'replaced by'search-autocomplete', and thesearchIdfrom the suggestions response instead of the results response.Autocomplete and the results gallery are distinct searches. Don't propagate the suggestions'
searchIdto the results screen when the shopper submits the search: that screen has its ownsearchId. -
On React Native, gate the tracking at render time, since it doesn't validate an empty
elementSourceat runtime: only mount the tracked component when there's asearchId.
Checklist
- Impression sent on every search, including searches that return no products.
searchIdalways coming from the API and present on both the impression and the click.productPositionis 1-based and correct after pagination or infinite scroll.- No event sent on a search that redirects or has no
searchId.