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.
Campaign links
Masivo preservesutm_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 existingPOST /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: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 protectedPURCHASE events. Forward the checkout’s
captured GA4 context with the purchase:
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
- Click a test link for Meta, Braze and Masivo. Check every destination URL and the decoded Play referrer for source, medium and campaign.
- Test web, installed app and fresh install. Verify that the tag/Firebase receives campaign context and generates the real identity/session.
- Send a confirmed test purchase from that session. Inspect its final payload, transaction ID, items, amount and currency, and check for duplicate emitters.
- Validate payloads with
/debug/mp/collectandvalidation_behavior: ENFORCE_RECOMMENDATIONS. This endpoint does not collect events or verify secrets. A2xxfrom/mp/collectalone does not prove that GA4 processed the event. - Verify actual receipt using a test property and inspect acquisition,
session and purchase reporting after processing.
campaign_detailsis not displayed in reports or DebugView; it is available in BigQuery export when enabled. Check its effect on attributed events instead.
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.