Skip to main content
Masivo sends events to Google Analytics 4 through Measurement Protocol. For session attribution, these events must join the identity and session collected by your website’s Google tag or your app’s Firebase Analytics SDK. Masivo link tracking in its own analytics does not automatically create a GA4 session.

Configure streams

In the Google Analytics destination, configure at least one complete stream: Each secret belongs to its corresponding GA4 data stream. Keep these secrets in Masivo’s destination configuration, never in links or client apps. Enable Sync events and/or Sync purchases, and include the desired event names in the allowed-events selection when using a restricted list. Existing measurement_id and api_secret settings remain the web stream. App settings are stored as android and ios objects, each containing firebase_app_id and api_secret. An app-only destination is supported. Test connection validates a sample payload for each configured stream using Google’s validation endpoint. It does not validate credentials or create events in reports. Verify receipt separately using the actual stream and identity. Masivo preserves utm_source, utm_medium, utm_campaign, utm_term, and utm_content. Non-empty incoming values override the stored destination’s values. Missing destination fields first use the selected fallback URL, including campaign fields inside a Play Store referrer. Only fields still missing on internal campaign links receive these defaults: The default campaign is the link’s campaign_id, or template_id if there is no campaign. Explicit values remain unchanged. In-app/news-feed navigation and external links do not receive automatic acquisition labels. Existing links use these rules when clicked, without rewriting stored links. For example, a Braze email should explicitly carry utm_source=braze and utm_medium=email. A Meta ad can use utm_source=facebook and utm_medium=paid_social, with its campaign in utm_campaign. Masivo preserves these labels rather than replacing the source with the name of the shortener. fbclid alone does not provide a manually tagged GA4 campaign. The same UTM context travels through the direct destination, HTTPS fallback, Android Intent and installed-app resolution ($app-found=true). Google Play receives UTM inside its encoded referrer, alongside Masivo’s tracking_id and link. Existing referrer fields are preserved. Editing UTM in the dashboard also preserves unrelated query parameters and URL fragments.

Event context

The existing POST /storefront/v1/behavior/events request accepts an optional ga4 object. Client SDK events accept the same object; it is forwarded with the event rather than collected automatically. Masivo rejects malformed contexts and identities for the wrong platform. Requests do not accept API secrets in this object. customer_id remains the Masivo customer identifier; it does not replace a real GA4 identity.

Web

Keep campaign parameters in the landing URL until the Google tag processes it. Obtain IDs through the tag API instead of parsing cookies:
Capture context when the event occurs. Do not keep a session ID indefinitely or reuse one from a different device. Follow the existing consent flow; if analytics is disabled, do not call the tag API or send analytics data.

Android and iOS

The host app supplies Firebase’s installation and session IDs using its Analytics SDK (getAppInstanceId/getSessionId on Android, appInstanceID/sessionID on iOS). It handles incoming universal/app links and custom schemes and passes their campaign information to Firebase. After masivo.deepLinks.resolveDeferred(...) returns a recovered URL, read its UTM parameters. If Firebase has not already recorded that campaign, log campaign_details with source, medium, campaign, term, and content. For first-install attribution, do this shortly after installation; Firebase owns first_open, so do not emit a synthetic first_open from Masivo. Preserve the returned tracking_id for Masivo attribution. Its value is not an app_instance_id. Resolution may return no match; iOS fingerprint matches are probabilistic and do not establish deterministic installation attribution. No Firebase dependency is required by the Masivo SDK itself. See Google’s app attribution guide and identity reference.

Purchases

Send confirmed purchases from your backend using a SERVER API key. The client SDK does not authorize protected PURCHASE events. Forward the checkout’s captured GA4 context with the purchase:
The IDs above are placeholders; replace them with the actual browser/app context. Masivo maps the order’s ID to transaction_id, products to items, sku to item_id, amount to quantity, and unit value to price. discounted_value takes precedence when supplied, including zero. Currency comes from the event or the account’s currency. Explicit native GA4 ecommerce fields take precedence over the equivalent order mapping. Unfulfilled Masivo orders wait for confirmation. Cancelled orders do not produce purchases. Reversals become refund with the original transaction ID and the reversal’s timestamp. Select one purchase emitter per flow: either the client tag/Firebase or this connector. Do not independently send the same purchase through both. Standard/ecommerce event names are lowercased. Other custom event parameters retain the existing event_ flattening, except campaign UTM and GA4 session context and debug_mode, which are sent without that prefix. Internal _type and _source_direction metadata are excluded. Invalid GA4 event names are moved to the error queue instead of being sent and silently rejected. Explicit campaign_details events use GA4’s native campaign field names; Masivo does not create a new campaign event for every purchase.

Legacy fallback and delivery

When a real identity is absent, Masivo preserves the previous behavior: customer_id is used as client_id on the web stream (anonymous if the queued data has no customer ID). A supplied session is omitted on this path because it belongs to a different identity. This compatibility path does not provide reliable session attribution. It requires a configured web stream, even when the event originated in an app. Valid app identities always select their app stream. Missing stream configuration is reported and queued messages remain pending; they are not silently sent to another stream. The cron logs per-account legacyIdentityCount and missingSessionCount for each processing batch. These count prepared events, not confirmed GA4 ingestion. Batches contain up to 25 events and separate platforms, identities and User-IDs. Each event retains its own session and issued_at timestamp. Session attribution requires the corresponding online session, delivery within 24 hours of its start and an event timestamp within that session. See Google’s Measurement Protocol requirements.

Verify the integration

  1. Click a test link for Meta, Braze and Masivo. Check every destination URL and the decoded Play referrer for source, medium and campaign.
  2. Test web, installed app and fresh install. Verify that the tag/Firebase receives campaign context and generates the real identity/session.
  3. Send a confirmed test purchase from that session. Inspect its final payload, transaction ID, items, amount and currency, and check for duplicate emitters.
  4. Validate payloads with /debug/mp/collect and validation_behavior: ENFORCE_RECOMMENDATIONS. This endpoint does not collect events or verify secrets. A 2xx from /mp/collect alone does not prove that GA4 processed the event.
  5. Verify actual receipt using a test property and inspect acquisition, session and purchase reporting after processing. campaign_details is not displayed in reports or DebugView; it is available in BigQuery export when enabled. Check its effect on attributed events instead.
For a test event, send top-level debug_mode: true alongside ga4. Masivo preserves it for standard and custom events. Enable debugging in the Google tag/Firebase implementation as well, select that device in DebugView, and include actual measured ga4.engagement_time_msec for Realtime checks. Remove debug mode when testing normal acquisition reports: an active developer-traffic filter may exclude debug events from those reports. See Google’s developer traffic filter guide. Historical attribution and unmatched installs cannot be reconstructed by changing link parameters. See Google’s validation guide and campaign_details reference.