← All entries

UTM tracking in Customer Insights – Journeys + Static CSV segment uploads

Praxisis D365 Wiki · Public reference · Client-specific details redacted

Source: Claude.ai chat (original: wait-time-tile-90-day-limit__00914bc4.md) Added: 2026-10-02

Summary

  • UTM parameters (utm_source, utm_medium, utm_campaign, utm_content, utm_term) are a Google Analytics convention, not a Microsoft thing. Nothing in D365 reads them back — they exist so your web analytics can attribute a session.
  • Enable in CIJ: Settings → Feature switches → UTM Tracking (on) · Settings → Customer engagement → UTM tracking (create one mapping record per business unit).
  • UTM insertion is gated by tracking consent. If Compliance Settings consent model is Restrictive and tracking-consent-from-customers is on, the contact must have explicitly opted in before tracking links go in — without consent, UTM codes are not inserted at all. Separate from email/SMS marketing consent.

Key takeaways

  • Default UTM mapping: utm_source = static text you set · utm_campaign = journey Name · utm_medium = channel (email/sms) · utm_content = message name · utm_term = not populated.
  • One UTM record per business unit max.
  • "Fixing missing UTMs" by flipping to non-restrictive is a privacy-policy decision, not a settings decision — it quietly turns on behavioural tracking for everyone. Flag to the client before anyone touches that toggle.
  • UTM tagging is distinct from D365's own link tracking (the marketingusercontent.com redirect links that feed journey analytics). Configured independently and can be consented differently.
  • UTM = Urchin Tracking Module (legacy name; Google acquired Urchin Software in 2005, parameter convention stuck).

Static CSV segment uploads

  • No feature switch — it's generally available but not where people look first. Two typical misses:
    1. The segment must be saved before you can add static members.
    2. Elements pane → Contacts tab is the search-by-name path (capped at 100 members). CSV upload lives at + Add a new group dropdown → inclusion/exclusion group → Upload CSV. Drag-and-drop onto the segment canvas also works.
  • CSV format: must have a header column emailaddress1 with addresses to match against existing Dataverse records. Email-only matching — no documented GUID / alternate-key option.
  • The header is the Dataverse logical name, not a friendly label — Email, Email Address, EMAILADDRESS1 may not be picked up. Test with a 2-row file before a 200K-row upload.
  • Duplicate emails fan out: three contacts sharing an address = one CSV row brings in all three. Rows with no match go to a "Not found" bucket you can push into Dataverse via standard contact/lead CSV upload and re-run.
  • Limits: 200,000 members per static group, max 10 groups → 2,000,000 ceiling. Static + dynamic criteria can coexist in one segment. Exclusion beats inclusion.
  • Business-unit scoping differs between static and dynamic: static snapshot only matches contacts the author can see under their BU/team scope. Dynamic query pulls all matching records at run time regardless of author's BU. A static CSV list built by a BU-scoped user will silently come back short.
  • No email, bulk size → use the segment builder API (anything the UI does is programmable) rather than hand-building email CSVs. The API path is far less painful when source is a GUID list or alternate key output from an existing data pipeline.
  • Manual Select members uses the Dataverse grid — fine for tens or hundreds, limited by browser cache, not for bulk.

Learnings / how to apply

  • "UTM depends on tracking consent" is a mandatory section of any CIJ consent-model handover doc — otherwise clients blame Google Analytics for "missing data" that is correctly suppressed by their own compliance setting.
  • Standard flow for nonprofit segment uploads: generate a GUID + email staging table → either (a) use emails for CIJ CSV upload (fan-out risk) or (b) use the segment API with GUIDs (safer for exact-cohort targeting). Document which path per client.
  • Pre-flight "test CSV header literally spells emailaddress1" is a one-line checklist item that prevents a 200K-row upload failure.

Need this applied to your own tenant?

Praxisis Sustain Self-Serve builds a private AI Wiki trained on your documents and tickets, with free Tier-2 support when the AI cannot answer. Book a 30-min overview.