UTM Tracking for MoEngage: How to Build and Validate Campaign Links
MoEngage is a multi-channel customer engagement platform covering push notifications (web and mobile), email, in-app messages, SMS, and WhatsApp. UTM tracking for MoEngage requires manually adding utm_source=moengage to every campaign URL — MoEngage does not auto-append UTM parameters to campaign links by default. The correct utm_medium depends on the channel: push for mobile and web push notifications, email for email campaigns, sms for SMS, in-app for in-app message CTAs that open external URLs, and whatsapp for WhatsApp campaigns. Push notifications and SMS have no HTTP referrer — without UTM parameters, GA4 classifies taps and clicks as Direct traffic. Build tracked MoEngage URLs with mlz build --source "moengage" --medium "push" (or the appropriate medium) before entering them in the MoEngage campaign builder, and run --validate to confirm the destination URL resolves correctly before launching.
Why MoEngage requires per-channel UTM tracking
MoEngage's strength is cross-channel orchestration — a single campaign flow can touch a user via push notification, follow up with an email, and then show an in-app message if the user opens the app. But this multi-channel architecture creates a UTM tracking challenge: if you use the same tracked URL across all channels in a Flow, GA4 cannot distinguish whether a session was driven by the push notification, the email, or the in-app message. The utm_medium parameter is what makes this distinction possible.
Push notifications are the highest-risk channel from an attribution perspective. When a user taps an MoEngage push notification, the device opens the campaign URL with no HTTP referrer header. GA4 classifies sessions with no referrer as Direct traffic — your push channel contribution disappears into the Direct baseline. Email traffic is less vulnerable (email clients often pass referrer headers), but UTM parameters on email links still give you explicit attribution that is more reliable than referrer-based inference. SMS links have no referrer at all — they behave exactly like push notifications from a GA4 attribution standpoint.
The only reliable solution for all channels is explicit UTM tagging: build a separate tracked URL for each channel within a Flow, using utm_medium to identify the delivery channel and a consistent utm_campaign slug to group all touchpoints from the same campaign or Journey together in GA4 reports.
| MoEngage channel | Referrer passed? | Without UTM | Recommended utm_medium |
|---|---|---|---|
| Mobile push (iOS / Android) | No | Direct in GA4 | ✓ push |
| Web push notification | No | Direct in GA4 | ✓ push |
| Email campaign | Often yes | Usually Email in GA4 | ✓ email |
| SMS campaign | No | Direct in GA4 | ✓ sms |
| In-app message (opens browser) | No | Direct in GA4 | ✓ in-app |
| WhatsApp campaign | No | Direct in GA4 | ✓ whatsapp |
Building tracked MoEngage campaign URLs with mlz build
MoEngage's campaign builders have a URL field for the redirect destination — in push notifications this is the "Redirect URL" or "CTA URL," in email it is any hyperlink, in in-app messages it is the button action URL, and in SMS it is the message link. Build your tracked URL with mlz build before opening the MoEngage campaign builder, then paste the tracked_url into the appropriate URL field for each channel. Use a separate mlz build call per channel step — changing only the --medium flag while keeping the same --campaign slug.
# Push notification step in a MoEngage Flow
$ mlz build \
--url "https://app.example.com/summer-sale" \
--source "moengage" \
--medium "push" \
--campaign "summer-sale-jun-2026" \
--validate
{
"tracked_url": "https://app.example.com/summer-sale?utm_source=moengage&utm_medium=push&utm_campaign=summer-sale-jun-2026",
"params": {
"utm_source": "moengage",
"utm_medium": "push",
"utm_campaign": "summer-sale-jun-2026"
},
"stored": true
}
# Email step in the same MoEngage Flow (same campaign, different medium)
$ mlz build \
--url "https://app.example.com/summer-sale" \
--source "moengage" \
--medium "email" \
--campaign "summer-sale-jun-2026" \
--validate
{
"tracked_url": "https://app.example.com/summer-sale?utm_source=moengage&utm_medium=email&utm_campaign=summer-sale-jun-2026"
}
# SMS step: same campaign slug, utm_medium=sms
$ mlz build \
--url "https://app.example.com/summer-sale" \
--source "moengage" \
--medium "sms" \
--campaign "summer-sale-jun-2026" \
--validate
{
"tracked_url": "https://app.example.com/summer-sale?utm_source=moengage&utm_medium=sms&utm_campaign=summer-sale-jun-2026"
}
In GA4, filter by utm_campaign=summer-sale-jun-2026 to see all sessions from this MoEngage campaign, then pivot on the utm_medium dimension to compare push, email, and SMS contributions side by side. The consistent utm_campaign slug groups all touchpoints from the same campaign, while distinct utm_medium values separate them by channel — giving you a complete multi-channel attribution picture without requiring any GA4 custom dimensions.
UTM tracking for MoEngage Flows (multi-step automation)
MoEngage Flows are multi-step automated campaigns that can include push notifications, emails, in-app messages, and SMS in a single orchestrated sequence — triggered by user behavior events such as app install, cart abandonment, or inactivity. When building a Flow, every step that links to an external URL needs its own tracked URL. Use a consistent utm_campaign slug across all steps in the Flow, and set utm_medium to match the channel for each step. Use utm_content to identify the specific step number or step name within the Flow.
# Step 1: Push notification (1 hour after cart abandonment)
$ mlz build \
--url "https://store.example.com/cart" \
--source "moengage" \
--medium "push" \
--campaign "abandoned-cart-flow" \
--content "push-step-1" \
--validate
{
"tracked_url": "https://store.example.com/cart?utm_source=moengage&utm_medium=push&utm_campaign=abandoned-cart-flow&utm_content=push-step-1"
}
# Step 2: Email (24 hours after abandonment)
$ mlz build \
--url "https://store.example.com/cart" \
--source "moengage" \
--medium "email" \
--campaign "abandoned-cart-flow" \
--content "email-step-2" \
--validate
{
"tracked_url": "https://store.example.com/cart?utm_source=moengage&utm_medium=email&utm_campaign=abandoned-cart-flow&utm_content=email-step-2"
}
# Step 3: SMS (48 hours after abandonment)
$ mlz build \
--url "https://store.example.com/cart" \
--source "moengage" \
--medium "sms" \
--campaign "abandoned-cart-flow" \
--content "sms-step-3" \
--validate
{
"tracked_url": "https://store.example.com/cart?utm_source=moengage&utm_medium=sms&utm_campaign=abandoned-cart-flow&utm_content=sms-step-3"
}
With this tagging structure, GA4's campaign report for utm_campaign=abandoned-cart-flow shows the total sessions, cart recoveries, and revenue generated by the entire Flow. The utm_medium dimension breaks down which channel drove each recovery, and utm_content shows which specific step in the Flow was the last touchpoint before the conversion. This is the minimum viable UTM structure for understanding a multi-step automated campaign — anything less makes it impossible to know which step is doing the work.
MoEngage UTM tracking gotchas
- MoEngage does not auto-append UTM parameters to campaign URLs by default
- MoEngage does not have a global setting that automatically appends UTM parameters to all campaign URLs. Every campaign step, every push notification's Redirect URL, every email hyperlink, and every SMS message link requires a manually tagged URL. Some MoEngage customers configure custom URL parameters at the campaign level in MoEngage's settings, but these are custom parameters — not standard UTM parameters — and GA4 does not read custom parameters as channel attribution without additional configuration. Build tracked URLs with
mlz buildbefore entering them in MoEngage to ensure standard UTM parameters are present on every campaign URL. - Using a single tracked URL across all channels in a Flow merges attribution
- A common shortcut is to build one tracked URL with
utm_source=moengage&utm_medium=pushand reuse it for all steps in a Flow. This is wrong for any step that is not a push notification — email clicks, SMS clicks, and in-app message CTAs with the same URL will all be attributed to the push channel in GA4. Build a separate tracked URL per channel step, differing only in theutm_mediumvalue. The extra build commands take less than a minute and give you channel-level attribution that is accurate, not just approximate. - MoEngage SMS uses link shortening — UTM parameters must be added before shortening
- MoEngage SMS campaigns can use MoEngage's built-in link shortening feature. If you add UTM parameters to the URL after it has been shortened by MoEngage, the parameters are appended to the short URL — but the redirect chain may or may not preserve them depending on how the short link resolver handles query strings. The safe approach is to build the fully tagged URL with
mlz buildfirst, then paste the tagged URL into the MoEngage SMS campaign builder before MoEngage applies any shortening. MoEngage shortens the fully tagged URL as a unit, and the redirect from the short link to the destination URL typically preserves query string parameters. Usemlz build --validateto confirm the destination resolves and the redirect chain is clean before the SMS campaign sends. - MoEngage in-app message CTAs that open external URLs need separate tracking from in-app screen navigation
- MoEngage in-app messages can have CTA buttons that either navigate within the app (in-app routing to a specific screen) or open an external browser URL. UTM parameters are only relevant for external browser URLs — in-app routing does not load a web URL and GA4 never sees the navigation event in the standard configuration. For in-app message CTAs that open external URLs (common for promotional in-app messages, feature announcements, or campaign landing pages), build a tracked URL with
utm_medium=in-appand enter it as the button action URL. For buttons that use in-app routing, no UTM tagging is needed or possible. - MoEngage WhatsApp campaigns may have shorter URL character limits
- WhatsApp message templates have character limits, and adding UTM parameters to campaign URLs in WhatsApp messages increases URL length. For WhatsApp campaigns where URL length is a concern, use
utm_source=moengage&utm_medium=whatsapp&utm_campaign=slugand keep the campaign slug concise — avoid utm_content and utm_term in WhatsApp URLs unless the character budget allows. If the fully tagged URL is too long for the WhatsApp template, use a URL shortener on the tagged URL (not on the bare URL) so the short link resolves to the tagged destination. Validate the short URL withmlz build --validateto confirm the redirect chain preserves UTM parameters.
MoEngage UTM naming conventions
Recommended UTM parameter values for MoEngage, aligned with GA4 channel reporting and a lowercase-hyphenated taxonomy:
- utm_source:
moengagefor all sends from the MoEngage platform across all channels. Always lowercase. Using a single source value for all MoEngage channels makes it easy to filter the GA4 acquisition report to see all MoEngage-attributed traffic regardless of channel. - utm_medium: Match the delivery channel —
pushfor mobile and web push notifications;emailfor email campaigns;smsfor SMS;in-appfor in-app message CTAs that open external browser URLs;whatsappfor WhatsApp campaigns. Add a GA4 custom channel grouping rule (Admin > Data Display > Channel Groups) to classifyutm_medium=pushunder a Push channel, as GA4 does not include Push in its default channel grouping. Similarly add rules forutm_medium=in-appandutm_medium=whatsappif you want dedicated channel rows in GA4 reports. - utm_campaign: A consistent slug per campaign or Flow. For one-off campaigns:
summer-sale-jun-2026,new-feature-launch-jun,weekly-digest-jun-7. For automated Flows:abandoned-cart-flow,onboarding-flow-day1,reengagement-flow-30d,win-back-flow-60d. Use the same campaign slug across all channel steps in a Flow so GA4 groups them together. - utm_content: Flow step identifier or A/B variant label. For multi-step Flows:
push-step-1,email-step-2,sms-step-3. For A/B tests:variant-a,variant-b. For in-app message CTA buttons:primary-cta,secondary-cta. Omit when a campaign has a single CTA, single step, and no variants. - utm_term: Rarely used for MoEngage campaigns. Consider for audience segmentation where the same campaign copy is sent to different behavioral segments with different destination experiences:
utm_term=high-value-users,utm_term=lapsed-30d.
See the UTM naming conventions guide for the full cross-platform reference and the UTM tracking for developers guide for programmatic generation and validation at scale.
FAQ
- Does MoEngage auto-tag campaign URLs with UTM parameters?
- No. MoEngage does not have a global auto-UTM setting that appends standard UTM parameters to all campaign links. MoEngage tracks campaign performance in its own analytics dashboard (delivered, clicked, conversion events) using MoEngage's internal tracking parameters — but these are not standard UTM parameters and GA4 cannot read them for session attribution. To correctly attribute MoEngage-driven sessions in GA4, you must manually add standard UTM parameters to every campaign URL before entering it in MoEngage's campaign builders.
- What utm_source should I use for MoEngage?
- Use
utm_source=moengagefor all campaigns sent through the MoEngage platform. Use a consistent single source value across all MoEngage channels (push, email, SMS, in-app, WhatsApp) rather than channel-specific source values likeutm_source=moengage-push— the channel distinction belongs inutm_medium, not inutm_source. A single source value makes it easy to filter GA4 to see all MoEngage-attributed traffic in one view, then pivot onutm_mediumto compare channel performance. - How do I track MoEngage Flows (automated sequences) in GA4?
- Use a consistent
utm_campaignslug for all steps in the Flow, matchutm_mediumto the channel for each step, and useutm_contentto identify each step (e.g.,push-step-1,email-step-2). In GA4, filter by theutm_campaignslug to see all sessions from the Flow, then pivot onutm_mediumto compare channel contributions and onutm_contentto compare step-level performance. This gives you a complete multi-touch picture of which Flow step and which channel drove conversions without requiring GA4 custom reports or custom dimensions. - MoEngage offers MoEngage Analytics — do I still need UTM parameters for GA4?
- Yes. MoEngage Analytics tracks MoEngage-specific events: notification delivery, notification click, in-app impression, email open, email click, and custom conversion events you define within MoEngage. It does not push session or channel data into GA4's acquisition reports. GA4's channel attribution is based on UTM parameters (and referrer headers where present) — it has no visibility into MoEngage's internal event data. If you want GA4's acquisition, user, and conversion reports to correctly attribute MoEngage-driven sessions, UTM parameters on every campaign URL are required, regardless of what MoEngage Analytics reports in its own dashboard.
- How do I validate MoEngage campaign URLs before launching?
- Run
mlz build --url "your-destination-url" --source "moengage" --medium "push" --campaign "your-campaign-slug" --validatefor each campaign URL before entering it in MoEngage. The--validateflag confirms HTTPS, resolution (200 response), redirect chain integrity, and query string preservation through any redirects. For landing pages that will also be shared on social or in other channels, runmlz inspect "your-tracked-url"to verify OG tags, Twitter Card metadata, and viewport configuration — a landing page built for a push campaign that is missing OG tags will render poorly if shared on social or linked from email. See the campaign link preflight check guide for the full pre-launch validation workflow.
Related reading
Build MoEngage campaign links from the terminal
Use mlz build --source "moengage" --medium "push" (or the channel-appropriate medium) to generate tracked URLs for every MoEngage campaign before entering them in the campaign builder. Build a separate URL per channel within each MoEngage Flow — using the same --campaign slug but a different --medium for each step. Add --content "push-step-1", --content "email-step-2", etc. to identify individual steps in GA4 reports. Add --validate to confirm each destination URL resolves correctly before the campaign launches. MoEngage campaigns that go out without UTM parameters will appear as Direct traffic in GA4 with no retroactive fix available.
npm install -g missinglinkz
Free plan: 1,000 links/month. No credit card. See the UTM tracking for developers guide for the full programmatic workflow including API and MCP integration.