Elido
12 Min. LesezeitTutorials
Eckpfeiler

UTM-Kampagnen Ende-zu-Ende ohne CDP tracken

Ein praxisnahes Playbook für Marketer: Workspace-UTM-Templates, Bulk-Import aus Sheets, serverseitige Conversion-Weiterleitung und der QA-Dry-Run, der Drift vor dem Launch erwischt

Ana Kowalska
Marketing solutions engineering
Five-step UTM pipeline: workspace template, campaign override, bulk import, server-side forward, GA4 DebugView verification

Ich habe UTM-Tracking bei drei Unternehmen Ende-zu-Ende verkabelt. Jedes Mal brachen dieselben fünf Dinge in derselben Reihenfolge, und jedes Mal war der Fix derselbe: Zieh das Templating auf die Kampagnen-Ebene hoch, schieb die Conversion-Weiterleitung auf den Server, und pack einen Dry-Run dazwischen. Das ist das meiste, was in diesem Beitrag steht. Der Rest ist die QA-Checkliste, die die Dinge erwischt, an deren Kaputtgehen du nicht gedacht hast.

Du brauchst dafür keine Customer Data Platform. Du wirst irgendwann eine brauchen, wenn dein Attributionsproblem wird "vier anonyme Touches über drei Geräte hinweg zu einer einzigen Kundenreise zusammennähen", aber für den Fall, den ich am häufigsten sehe - "jeden ausgehenden Link konsistent taggen, den Click erfassen, die Conversion serverseitig an Meta und GA4 weiterleiten und Safari überleben" - erledigt ein URL-Shortener mit Templates plus einer Conversions-API den Job. Unten ist die Version, die funktioniert, mit den Failure-Modes, die ich gesehen habe.

Was bei UTM-Tracking schiefgeht#

Die Marketer, mit denen ich arbeite, sind nicht schlecht in UTMs. Das Problem ist, dass die Tools standardmäßig darauf ausgelegt sind, es einfach zu machen, ein UTM einmal zu tippen, schwer, eines unternehmensweit durchzusetzen, und unmöglich, es nach dem Launch zu fixen. Vier Failure-Modes tauchen immer wieder auf.

Drift. Eine Person tippt utm_source=newsletter, eine andere tippt utm_source=Newsletter, eine dritte tippt utm_source=email. Sechs Monate später ist dein "Newsletter"-Kanal in GA4 über neun String-Varianten verteilt. Es im Nachhinein aufzuräumen ist eine Regex-und-bete-Übung. Das ursprüngliche urchinTracker()-Script, das diese Konvention einführte - Googles Pre-Analytics-Urchin-Webanalyse-Produkt, 2003 kurz Open Source, bevor es absorbiert wurde - hatte ebenfalls keine Template-Schicht. Die Konvention war immer "tipp es konsistent"; das Tooling hat es nie erzwungen.

Manuelles Tagging im großen Maßstab. Eine Flyer-Kampagne mit 80 Short Links über vier regionale Storefronts sind 320 URLs, die du abtippen, in ein Spreadsheet einfügen, in deinen Shortener kopieren und beten musst. Die Hälfte davon bekommt das falsche utm_content. Niemand bemerkt es, bis die Kampagne zwei Wochen alt ist.

Serverseitige Conversion-Lücken. Der Pixel feuert auf der Danke-Seite, GA4 nimmt ihn auf, Meta nimmt ihn auf, und du gehst nach Hause. Dann liefert Safari eine weitere ITP-Version aus, Ad-Blocker-Installationen steigen, und deine berichteten Conversions sinken um ein Drittel. Apples ITP-2.3-Release-Notes gehen genau den Mechanismus durch: Link-Dekoration wird gedrosselt, document.referrer wird entfernt, und jeder Analytics-Flow, der darauf angewiesen ist, dass der Browser Drittanbieter-JS ausführt, degradiert still. Die Conversions passieren immer noch auf deinem Server. Sie schaffen es nur nicht zu den Ad-Surfaces.

Kein Dry-Run. Die erste Conversion, die durch die neue Pipeline fließt, ist der erste echte Käufer. Wenn etwas falsch konfiguriert ist, findest du es drei Tage später heraus, wenn der Optimierungsalgorithmus bereits Budget aus einer Kampagne abgezogen hat, die eigentlich funktionierte.

Dieser Beitrag adressiert die ersten drei mit Templates + Bulk-Import + serverseitiger Weiterleitung, und den vierten mit einem Verifikationsschritt, der leicht zu überspringen und teuer zu überspringen ist.

Workspace- und Kampagnen-UTM-Templates#

Templates schieben das Konsistenzproblem den Stack hinauf. Du definierst deine Tagging-Konvention einmal auf Workspace-Ebene, schichtest dort, wo gerechtfertigt, Pro-Kampagnen-Overrides darüber und lässt jeden Link erben. Es gibt keinen Ort mehr, an dem ein Tippfehler leben könnte.

Definiere zuerst die Workspace-Defaults. Literale Werte fixieren die Variablen, die sich für deine Organisation nie ändern (utm_medium = email für Newsletter-Kampagnen); Platzhalter füllen sich beim Anlegen aus dem Link-Payload:

curl -X PUT \
  https://api.elido.app/v1/workspaces/1/utm-template \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "utm_source":   "{{ channel }}",
    "utm_medium":   "{{ medium }}",
    "utm_campaign": "{{ campaign }}",
    "utm_content":  "{{ creative }}",
    "utm_term":     "{{ audience.segment }}"
  }'

Ein paar Details, die hier zählen:

  • Die Platzhalter werden bei der Link-Erstellung gefüllt, nicht bei der Click-Zeit. Was in deinem Analytics-Tool landet, ist das, was zu dem Moment beabsichtigt war, in dem der Link geprägt wurde - nicht das, was das Ziel des Links beim Click berechnet hat. Das macht die Rekonstruktion des Audit-Logs viel einfacher, wenn sechs Monate später etwas falsch aussieht.
  • Unbekannte Platzhalter scheitern schnell. Wenn deinem Bulk-Import eine creative-Spalte fehlt und das Workspace-Template {{ creative }} referenziert, gibt die API ein 422 mit dem nicht aufgelösten Variablennamen zurück. Keine stille teilweise Anwendung.
  • Die vollständige Template-Referenz, inklusive link.tag.<name>-Platzhaltern, die aus dem Tag-Array des Links lesen (nützlich für Multi-Tenant-Agenturen, die einen Kunden-Identifier in jede URL einbetten müssen), ist in der Dokumentations-Anleitung.

Dann schichte ein Kampagnen-Template darüber. Kampagnen erben vom Workspace und ersetzen die Untermenge, die kampagnenspezifisch ist:

curl -X POST \
  https://api.elido.app/v1/campaigns \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "name": "Spring 2026 - DACH",
    "utm_template": {
      "utm_campaign": "spring_2026_dach",
      "utm_term":     "{{ audience.locale }}"
    }
  }'

Alles, was auf der Kampagne nicht gesetzt ist, fällt auf die Workspace-Defaults zurück. Die Zwei-Ebenen-Schichtung deckt die meisten realen Organisationsstrukturen ab: geteilte Konventionen auf Workspace-Ebene, team- oder saison-spezifische Overrides auf Kampagnen-Ebene. Wenn du dir eine dritte Ebene der Vererbung wünschst, ist das ein Geruch - normalerweise heißt das, dass zwei Kampagnen eine Kampagne mit schlaueren Platzhalter-Werten sein sollten.

Campaigns page in the Elido dashboard, four campaigns with their UTM defaults filled in: Spring 2026 launch (newsletter / email), Newsletter weekly, Influencer DACH Q2 (creator / partner), Paid social Meta retargeting

Was Per-Link-Overrides aufgeben: Ein Override feuert unabhängig vom Template. Was sie behalten: Der Override wird im Audit-Log mit Akteur + Zeitstempel + dem Aufgelöst-vs-Final-Diff aufgezeichnet. Sechs Monate später, wenn jemand fragt, warum ein Link in einer 200-Link-Kampagne utm_term=manual_override hat, kannst du antworten.

Bulk-Import aus Sheets - der Workflow, den die meisten Marketer tatsächlich nutzen#

Marketer sitzen nicht den ganzen Tag in curl. Das Kampagnen-Briefing landet als Spreadsheet mit Ziel-URLs und Kampagnen-Metadaten, die Launch-Deadline ist Freitag, und die Frage ist, wie dieses Spreadsheet zu 200 Short Links wird, ohne dass jemand denselben UTM-String 200 Mal tippt.

Die CSV-Spaltennamen passen zu den Platzhalter-Namen aus deinem Template (Groß-/Kleinschreibung wird ignoriert). Spalten, die Elido nicht erkennt, werden mit einer Warnung verworfen statt still kopiert - das ist beabsichtigt. Stilles Kopieren ist, wie du am Ende utm_brand_color in GA4 auftauchen siehst, weil jemand eine Spalte für eine interne Notiz hinzugefügt hat.

destination_url,channel,medium,creative
https://shop.example.com/de,newsletter,email,hero_a
https://shop.example.com/fr,newsletter,email,hero_a
https://shop.example.com/de,paid_social,meta,carousel_v2
https://shop.example.com/fr,paid_social,meta,carousel_v2

POST es als Multipart:

curl -X POST \
  https://api.elido.app/v1/links/bulk \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -F "csv=@launch_q2.csv" \
  -F "campaign_id=cmp_8a2f"

Zwei Dinge, die dir dieser Validierungs-Flow kauft, die eine Ein-Link-zu-einer-Zeit-UI nicht tut:

  • Alles-oder-nichts-Commit. Eine einzige fehlerhafte Zeile bricht den gesamten Upload ab und gibt die fehlerhaften Zeilennummern plus den Grund zurück - row 47: unresolved variable {{ creative }} ist ein viel besserer Fehler, als am Freitag um 16 Uhr zu entdecken, dass 47 deiner 200 Links zu einem Platzhalter-String aufgelöst wurden.
  • Pre-Launch-Vorschau. Die Bulk-Import-Vorschauzeile des Dashboards zeigt die aufgelöste URL inklusive des gerenderten utm_*-Query-Strings vor dem Commit. Schau dir den zweiten Link an, um sicherzugehen, dass dein Template das tat, was du erwartet hast, dann den letzten Link, um sicherzugehen, dass Zeilen weiter unten in der Datei nicht abgedriftet sind. Zwei Blicke, eine Minute.

Wenn dein Spreadsheet keine stabile Form hat - Spaltenreihenfolgen mischen sich, Header werden umbenannt - wird der Bulk-Import-Endpunkt unangenehm. Der Fix ist nicht in unserem Tooling; der Fix ist, sich auf ein CSV-Schema für deine Kampagnen-Briefings festzulegen und Schema-Drift als Prozess-Bug zu behandeln. Wir diskutieren das breitere Muster auf der Marketer-Solutions-Seite.

Serverseitige Conversion-Weiterleitung zu Meta CAPI und GA4#

Pixel-only-Attribution verliert 20–40% der Conversions an Safari ITP, Ad-Blocker und Consent-Banner. Die Zahl variiert nach Branche - DTC-Ecommerce sieht das obere Ende des Bereichs, B2B-SaaS das untere Ende - aber jede Messung, die ich Post-iOS-14 gesehen habe, setzt die Pixel-Zuverlässigkeit deutlich unter die 95%-Marke, die Werbeplattformen voraussetzen. Der Optimierungsalgorithmus bekommt rauschendere Inputs und dein CPA sieht schlechter aus, als er ist.

Metas Conversions-API-Dokumentation ist hierzu explizit: Server-Events sind das, was du willst, browserseitige Pixel sind die Ergänzung. GA4s Measurement Protocol macht denselben Fall. Beide Protokolle akzeptieren dieselbe Form: ein serverseitiges Event mit den Conversion-Details, eine event_id zur Deduplizierung und idealerweise gehashte Nutzer-Identifier, sodass die Plattformen die Conversion mit einem bekannten Besucher verbinden können.

Die Verkabelung, die die Lücke schließt, ist mechanisch. Drei Schritte.

Schritt eins - den click_id erfassen. Jede Elido-Redirect-Antwort trägt einen X-Elido-Click-Id-Header. Die TS- / Python- / Go-SDKs machen ihn auf dem Redirect-Response-Objekt verfügbar; rohes HTTP funktioniert auch:

curl -sI https://elido.me/launch | grep -i click-id
# X-Elido-Click-Id: clk_01HYZ7T8WV6KQX3M

Pack ihn in ein First-Party-Cookie auf der Zielseite (elido_click_id, 90-Tage-TTL - lang genug, um eine typische SaaS-Evaluation abzudecken, kurz genug, um die ePrivacy-Vorgabe zu erfüllen). Lies ihn beim Checkout zurück.

Schritt zwei - die Ziele verkabeln. PUT die Credentials für die Surfaces, an die du weiterleiten willst. Jede Teilmenge funktioniert; fehlende Surfaces werden still übersprungen:

curl -X PUT \
  https://api.elido.app/v1/workspaces/1/conversion-forwarding \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "meta_capi": {
      "pixel_id": "1234567890",
      "access_token": "EAA…",
      "test_event_code": null
    },
    "ga4_mp": {
      "measurement_id": "G-ABC123",
      "api_secret": "abc_def_ghi"
    },
    "mixpanel": {
      "project_token": "pm_…",
      "service_account": "[email protected]"
    }
  }'

Schritt drei - die Conversion POSTen. Wenn die Bestellung feuert, sende das Event mit dem click_id und den Bestelldetails. event_id ist dein Idempotenz-Schlüssel:

curl -X POST \
  https://api.elido.app/v1/conversions \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "click_id":   "clk_01HYZ7T8WV6KQX3M",
    "event_name": "purchase",
    "event_id":   "ord_98231",
    "value":      89.00,
    "currency":   "EUR",
    "user": {
      "email":  "[email protected]",
      "phone":  "+4915123456789",
      "external_id": "cust_5128"
    }
  }'

Nutzer-Identitätsfelder werden vor der Weiterleitung an Meta und GA4 SHA-256-gehasht - das verlangen beide Plattformen. Der UTM-Kontext wird aus der Click-Zeile gezogen, die zum click_id matcht, sodass das weitergeleitete Event die ursprüngliche Kampagnen-Attribution trägt, auch wenn der Nutzer eine Stunde auf der Seite herumgewandert ist, bevor er ausgecheckt hat. Die vollständige Mechanik, inklusive Refund-Handling und dem Multi-Touch-Attribution-Modell-Toggle, ist in der Conversion-Forwarding-Anleitung.

Conversion-tracking pixel admin tab in the Elido dashboard, with fields for Meta Pixel ID, Google Ads / GA4 ID, LinkedIn Insight Tag, and TikTok Pixel Code

Das ist der größte Teil der geschlossenen Lücke. Es gibt ein Restloch - Besucher, die das click_id-Cookie blockieren, oder über einen Nicht-Elido-Pfad ankommen - aber für die Kampagnen, in die du tatsächlich Traffic treibst, bist du von "60-80% Pixel-Zuverlässigkeit" auf "95%+ Server-Zuverlässigkeit" gewechselt.

Drei Edge-Cases, in denen das Audit-Log dich rettet#

Templates und Weiterleitung handhaben den Happy Path. Die Fälle unten tauchen in Woche drei jeder nichttrivialen Kampagne auf, und die richtige Antwort auf alle lebt im Audit-Log + dem Conversions-Panel - nicht im Versuch, ein ausgefeilteres Template zu entwerfen.

Refunds. Eine Kauf-Conversion ist gefeuert, der Kunde hat den Artikel eine Woche später zurückgegeben, und dein berichteter Umsatz ist jetzt 8% zu hoch. Der Fix ist, dasselbe event_id mit event_name: "refund" zu POSTen. Meta und GA4 behandeln das als negative Conversion gegen das Original; Mixpanel zeichnet es als separates Event auf, das du in deinem Funnel abziehst. Der Grund, warum event_id so geformt ist: Idempotenz auf Event-ID-Ebene heißt, dass du den Refund auch nicht doppelt zählen kannst. Das vollständige Muster ist im Edge-Cases-Abschnitt der Conversion-Forwarding-Anleitung dokumentiert - Refunds, Teilerstattungen und Gutschriften haben jeweils eine leicht andere Form.

Click-id-Misses. Eine Conversion feuert mit einem click_id, der zu keinem bekannten Click passt - Tippfehler, über die Aufbewahrung hinaus abgelaufen, falscher Workspace. Die Conversion wird trotzdem gegen den Workspace aufgezeichnet, aber mit leerem UTM-Kontext weitergeleitet. Das ist beabsichtigt: Catch-all-Attribution ist nützlicher, als die Conversion auf den Boden fallen zu lassen, und das click_id_unknown-Flag im Audit-Log lässt dich beim Reporting nach dem nicht attribuierten Anteil filtern. Wenn der Anteil größer als 5% der Conversions ist, stimmt etwas damit nicht, wie du den click_id auf der Zielseite persistierst - normalerweise das SameSite-Attribut des Cookies oder der Path-Scope.

Spät eintreffende Conversions. Ein B2B-SaaS-Verkauf schließt 47 Tage nach dem ursprünglichen Click ab. Elidos Standard-Click-Retention beträgt 30 Tage, also ist der Click bis zum Feuern der Conversion gealtert, und du bist im Click-id-Miss-Fall oben. Zwei Fixes, abhängig von deinem Verkaufszyklus: Erhöhe die Retention auf dem Workspace auf 90 Tage (Pro-Plan und höher) oder erfasse den click_id auf einem langlebigen First-Party-Identifier (der original_click_id-Spalte deines Kundenrekords), sodass du ihn zur Conversion-Zeit zurückverbinden kannst, auch wenn das Cookie weg ist. Wir haben beide Muster in Produktion gesehen.

Das Audit-Log zeigt das Aufgelöst-vs-Final-UTM-Diff pro Link, den Forwarding-Response-Code pro Ziel pro Conversion und den click_id-zu-Conversion-Join-State. Wenn der Optimierungsalgorithmus Budget aus einer Kampagne abzieht, die unterperformend aussieht, ist das Audit-Log das, was dich sagen lässt: "Nein, die Kampagne ist in Ordnung; wir haben drei Tage Forwarding an ein rotiertes GA4-api_secret verloren." Schau es dir an.

Die Pre-Launch-QA - Dry-Run der gesamten Pipeline#

Lass die erste Conversion, die hier durchfließt, nicht ein echter Käufer sein. Die Kosten eines 30-minütigen Dry-Runs trägst komplett du; die Kosten einer falsch konfigurierten Pipeline trägt der Optimierungsalgorithmus, der zwei Tage lang Budget aus deiner am besten performenden Kampagne abzieht, bevor du es bemerkst. Die Asymmetrie ist schlecht.

Drei Schritte, in Reihenfolge.

Bulk-Import-Dry-Run. Der Bulk-Import-Endpunkt akzeptiert dry_run=true als Query-Parameter. Er führt die Validierung durch, löst die Templates auf und gibt die anzulegenden Links zurück, ohne zu committen. Öffne die Antwort in einem beliebigen JSON-Viewer; die aufgelöste URL jeder Zeile ist sichtbar. Stichproben-prüfe 3–5 Zeilen: den zweiten Link, den letzten Link und alle Zeilen, die Workspace-Defaults überschrieben haben. Verifiziere, dass der utm_*-Query-String genau das ist, was dein Kampagnen-Briefing sagt.

Conversion-Forwarding-Testmodus. Meta CAPI akzeptiert einen test_event_code-Parameter, der das Event in den Test-Events-Tab im Events Manager statt in die Produktion routet. Setze ihn in der Workspace-Forwarding-Config, sende 10–20 Beispiel-Conversions und bestätige, dass sie landen. Gleiche Idee für GA4: Setze debug_mode: true auf den Events und verifiziere in DebugView. Beide sind Echtzeit. Der Punkt ist nicht, stichproben-zu-prüfen, dass die API funktioniert; der Punkt ist, eine falsch konfigurierte pixel_id oder ein api_secret, das rotiert und nie aktualisiert wurde, zu erwischen.

End-to-End-Smoke. Klicke einen deiner echten Short Links aus einer sauberen Browser-Session. Beobachte den Click im Recent-Clicks-Panel des Elido-Dashboards. Tu so, als hättest du etwas gekauft - POSTe eine purchase-Conversion mit diesem click_id aus deinem Terminal. Bestätige, dass die Conversion in Meta Test Events und GA4 DebugView mit dem richtigen UTM-Kontext erscheint. Die gesamte Schleife dauert unter 10 Minuten, sobald du sie einmal gemacht hast.

Nachdem alle drei bestanden sind, lasse den test_event_code weg, setze debug_mode: false und shippe. Der erste echte Käufer hat eine saubere Pipeline, die auf ihn wartet.

Conversions panel in the Elido dashboard showing total conversions and revenue, top links by revenue, daily revenue chart over the last 30 days, and revenue by platform breakdown

Wann du tatsächlich eine CDP willst#

Templates plus Bulk-Import plus serverseitige Weiterleitung bringt dich den größten Teil des Weges. Es gibt eine Klasse von Problemen, in der das nicht reicht, und nach einer CDP zu greifen ist die richtige Entscheidung.

Cross-Device-Identitätsverknüpfung. Ein Besucher klickt einen Link auf Mobile, konvertiert nicht, kommt auf Desktop zurück, meldet sich an. Du willst beide Touches derselben Person zugeordnet haben. UTM-Tracking + click_id ist Touch-Level; die Nutzer-Identitätsschicht, die die zwei Touches zu einer Reise macht, ist das, wofür eine CDP (Segment, mParticle, RudderStack) gebaut ist. Elido speichert bis zu 30 Tage Clicks pro Besucher und unterstützt Last-Touch- / First-Touch- / Position-Based-Attribution innerhalb dieses Fensters, aber der Cross-Device-Join braucht einen Identitätsgraphen, den wir absichtlich nicht betreiben.

Sub-100ms-Personalisierung. Wenn du die Zielseite basierend auf den früheren Touches des Besuchers in Echtzeit renderst - die Kohorte aus einem Feature-Store ziehst und die Hero-Headline variierst - brauchst du die Identitätsauflösung nahe am Render. Das ist CDP-Territorium oder, häufiger, eine Experimentplattform wie PostHog oder LaunchDarkly, die obendrauf geschichtet wird.

Multi-Touch-Attribution im großen Maßstab. Last-Touch ist für die meisten Kampagnen in Ordnung. Wenn dein Verkaufszyklus sechs Touches über vier Monate hat und du tatsächlich jedem Credit geben musst, bist du im Territorium, in dem Markov-Ketten- oder Shapley-Wert-Attribution wichtig wird. Elido macht Last-Touch / First-Touch / Position-Based; alles Anspruchsvollere will ein Tool mit einem ordentlichen Identitätsgraphen und einer Modell-Schicht.

Für alles andere - und "alles andere" ist die meisten Marketing-Teams, mit denen ich gearbeitet habe - reicht das Muster Templates + Bulk-Import + serverseitige Weiterleitung aus. Richte das Workspace-Template einmal ein, das Kampagnen-Template pro Launch, die Forwarding-Config einmal pro Plattform-Integration, und lass vor jedem Launch den Dry-Run laufen. Wenn du alle vier tust, hast du eine straffere UTM-Pipeline als 80% der Marketing-Teams, die ich auditiert habe.

Bau es einmal, mach vor jedem Launch einen Dry-Run und mach mit der nächsten Kampagne weiter.

Verwandtes im Blog#

Elido testen

URL einfügen, kurzer Link in Sekunden

Kein Konto nötig. Link bleibt 30 Tage aktiv. Konto erstellen, um ihn dauerhaft zu behalten.

Kostenlos, keine Anmeldung erforderlich · 2 pro Tag

Elido testen

URL-Shortener mit EU-Hosting: eigene Domains, tiefe Analytik und eine offene API. Kostenloser Tarif - keine Kreditkarte nötig.

Tags
utm tracking
utm template
utm builder
utm attribution
conversion forwarding
ga4
meta capi

Weiterlesen