Anwendungsfälle

Sign-ups in deiner App tracken (inkl. Google & Microsoft SSO)

Feuere ein Lead-Event, wenn jemand in deiner SaaS ein Konto erstellt – für das E-Mail/Passwort-Formular und für die Registrierung über Google und Microsoft (SSO). Der Form-Listener erkennt SSO-Registrierungen nicht, also sendest du das Event selbst – mit einer kleinen Server-Route und der Click-ID über den OAuth-state-Parameter.

Wenn die Aktion, die dich interessiert, in deiner eigenen Software passiert – jemand erstellt ein Konto – willst du in der Regel ein Lead-Event an LeadJourney senden, mit Name und E-Mail des neuen Users, zugeordnet zum Werbe-Klick, der ihn gebracht hat. Diese Anleitung zeigt genau wie – inklusive Registrierung über Google und Microsoft, die der automatische Form-Listener allein nicht erfassen kann.

Tracking muss zuerst live sein

Sign-ups werden dem Besucher zugeordnet, der auf deine Anzeige geklickt hat – das Tracking-Script muss also zuerst auf deiner Seite laufen. Falls nicht, beginne mit Tracking-Script einbinden (und den Entwickler-Hinweisen unter Auf einer custom-coded Website einbinden).

Warum der automatische Form-Listener nicht reicht

Das LeadJourney-Script feuert automatisch ein Lead, wenn es einen normalen <form>-Submit sieht. Das deckt dein einfaches E-Mail/Passwort-Formular ab. Es deckt nicht die Registrierung über Google oder Microsoft ab, denn dieser Ablauf sendet auf deiner Seite nie ein Formular:

  • Der Besucher verlässt deine Seite Richtung accounts.google.com / login.microsoftonline.com, bestätigt dort und wird zurück zu deinem Callback geleitet. Es gibt keinen <form>-Submit, den das Script erfassen könnte.
  • Das Konto wird oft serverseitig in diesem Callback erstellt – wo es gar keinen Browser zum Auslesen gibt.
  • Ein Klick auf den SSO-Button ist mehrdeutig – es könnte ein Login sein, keine neue Registrierung. Du willst das Event nur bei einem neuen Konto.

Für Sign-ups sendest du das Lead-Event also selbst, genau einmal, in dem Moment, in dem ein neues Konto erstellt wird. Das sind drei kleine Teile: eine Server-Route, die deinen Secret hält, ein Aufruf nach erfolgreicher Registrierung und – bei SSO – das Durchreichen der Click-ID über den OAuth-state-Parameter.

Die Click-ID ist der Schlüssel

Wenn ein Besucher über einen getrackten Link kommt, speichert das Script seine Click-ID im Browser. Diese ID ist es, die das neue Konto mit genau der Kampagne, Anzeigengruppe und Anzeige verbindet. Siehe Wie Attribution funktioniert. Woher deine App die ID ausliest, hängt davon ab, wo das Script installiert ist – das klärt der nächste Abschnitt.

Woher deine App die Click-ID bekommt

Es gibt zwei Setups, je nachdem, wo das Tracking-Script läuft. Prüfe zuerst, welches deins ist – jeder Codeschnipsel in dieser Anleitung geht davon aus, dass die Click-ID am Ende im localStorage liegt.

Option 1: Das Script läuft auch auf deiner App-Domain

Ist das Tracking-Script auch auf der App-Domain installiert (z. B. app.deinebrand.de), legt das Script die Click-ID direkt dort ab. Du liest sie einfach aus – nichts weiter vorzubereiten:

const clickId = localStorage.getItem("clickId");

Option 2: Das Script läuft nur auf deiner Root-Domain

Ist das Script nur auf deiner Marketing-Seite (deinebrand.de) installiert und nicht in der App, ist der localStorage der App-Domain leer – Browser teilen den Speicher nicht zwischen (Sub-)Domains. Stattdessen wird die Click-ID per URL an die App übergeben: Wenn der Besucher von deiner Seite in die App wechselt, reist sie als click_id-Parameter mit:

https://app.deinebrand.de/signup?click_id=8f3c…

In der App liest du die ID also aus der URL statt aus dem localStorage – einmal, auf der ersten Seite, auf der der Besucher landet – und hebst sie auf, bis die Registrierung abgeschlossen ist:

// Einmal beim Seitenaufruf in deiner App ausführen
const fromUrl = new URLSearchParams(window.location.search).get("click_id");
if (fromUrl) localStorage.setItem("clickId", fromUrl);

Danach funktioniert localStorage.getItem('clickId') genau wie in Option 1, und der Rest dieser Anleitung gilt unverändert für beide Setups.

Der Parameter muss den Sprung überleben

Egal welcher Button oder Link Besucher von deiner Seite in die App schickt – der click_id-Parameter muss mit ankommen. Wenn ein Redirect oder ein fest verdrahteter Link ihn verschluckt, hat die App nichts zum Auslesen. Siehe Cross-Domain-Tracking dazu, wie die Click-ID zwischen Domains reist.

Bevor du startest

Hol dir deine Conversion-API-Zugangsdaten unter Settings → Events → Conversion API:

  • Deine Postback-URL – sieht aus wie https://api.leadjourney.io/api/v1/postback/<deine-id>.
  • Dein Postback-Secret – beginnt mit pb_…. Behandle ihn wie ein Passwort; er bleibt auf deinem Server und wird nie im Browser sichtbar.

Stell sicher, dass im Events Manager ein Lead-Event existiert – jeder Workspace hat standardmäßig eins.

Schritt für Schritt

Eine Server-Route hinzufügen, die das Senden übernimmt

Diese eine Route leitet die Registrierung an LeadJourney weiter und hält deinen Postback-Secret sicher auf dem Server – für Besucher nie sichtbar. Das Beispiel ist eine Next.js-App-Router- Route, aber jeder Server-Endpunkt (Express, eine Serverless-Funktion, dein Backend) funktioniert genauso.

// app/api/lead/route.js
export async function POST(req) {
  const d = await req.json();

  await fetch(
    "https://api.leadjourney.io/api/v1/postback/YOUR-POSTBACK-ID",
    {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_POSTBACK_SECRET",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        type: "Lead",
        click_id: d.click_id,
        tag: d.tag,
        firstname: d.firstname,
        lastname: d.lastname,
        email: d.email,
      }),
    }
  );

  return Response.json({ ok: true });
}

Nutze deine eigene URL und deinen eigenen Secret

Ersetze YOUR-POSTBACK-ID und YOUR_POSTBACK_SECRET durch die Postback-URL und den Postback-Secret aus deinen eigenen Settings → Events → Conversion API. Schreibe den Secret nie in Client-Code und committe ihn nie in ein öffentliches Repo.

Sie aufrufen, wenn ein neues Konto erstellt wird

Überall dort, wo die Registrierung erfolgreich abschließt – das Formular, der Google-Button und der Microsoft-Button – fügst du diesen einen Aufruf hinzu. Die Click-ID liest du aus dem Browser (mit dem Option-2-Schnipsel von oben funktioniert localStorage in beiden Setups):

fetch("/api/lead", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    click_id: localStorage.getItem("clickId"),
    tag: "app_signup",          // dein Kampagnen-/Quellen-Tag – ein festes Wort genügt
    firstname: /* siehe Tabelle unten */,
    lastname:  /* siehe Tabelle unten */,
    email:     /* siehe Tabelle unten */,
  }),
});

Einmal senden, nur bei der Registrierung

Feuere das nur, wenn ein neues Konto erstellt wird – nicht bei jedem Login. Beim Login zu senden würde doppelte Leads erzeugen.

Die Werte aus der Registrierung einsetzen

Das ist der einzige Teil, den du von Hand mappst. Die Feldnamen unterscheiden sich je Anbieter leicht:

Zu sendendes FeldWas reinkommt
firstnameDer Vorname, den der User eingegeben hat
lastnameDer Nachname, den der User eingegeben hat
emailDie E-Mail-Adresse des Kontos
click_idlocalStorage.getItem('clickId') – siehe woher die ID kommt
tagDein Kampagnen-/Quellen-Tag (ein festes Wort genügt)

Das ist das Formular, das der automatische Listener erfassen würde – aber es hier selbst zu senden hält alle drei Registrierungs-Wege konsistent und liefert dir Name und E-Mail an derselben Stelle.

Google liefert das Profil aus dem ID-Token / der userinfo. Mappe es so:

Zu sendendes FeldGoogle-Feld
firstnamegiven_name
lastnamefamily_name
emailemail
click_idAus dem OAuth-state – siehe unten
tagDein Kampagnen-/Quellen-Tag

Microsoft (Entra ID / Microsoft-Konto) nutzt andere Property-Namen:

Zu sendendes FeldMicrosoft-Feld
firstnamegivenName
lastnamesurname
emailmail (Fallback: userPrincipalName)
click_idAus dem OAuth-state – siehe unten
tagDein Kampagnen-/Quellen-Tag

Die Click-ID durch Google / Microsoft SSO durchreichen

Bei SSO gibt es eine Sache extra zu lösen: die Click-ID von vor dem Redirect zu deinem Callback danach zu bringen. localStorage ist eventuell weg, wenn das Konto erstellt wird – der Callback kann serverseitig laufen oder auf einer anderen Subdomain landen.

Der Trick: der OAuth-state-Parameter

Pack die Click-ID in den OAuth-state-Parameter, bevor du weiterleitest. Google und Microsoft geben state unverändert im Callback zurück – die Click-ID übersteht also den ganzen Round-Trip, und du kannst sie serverseitig auslesen. Im Callback dekodierst du sie und sendest sie mit dem Lead.

1. Wenn der User auf „Mit Google / Microsoft fortfahren" klickt, pack die Click-ID in state:

const clickId = localStorage.getItem("clickId") || "";

// Pack die Click-ID in `state`. Füge hier auch dein CSRF-Token hinzu, falls du eins nutzt.
const state = btoa(JSON.stringify({ clickId, csrf: yourCsrfToken }));

// Google – Microsoft ist dieselbe Idee mit login.microsoftonline.com/common/oauth2/v2.0/authorize
const url = new URL("https://accounts.google.com/o/oauth2/v2/auth");
url.searchParams.set("client_id", GOOGLE_CLIENT_ID);
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", "openid email profile");
url.searchParams.set("state", state);

window.location.href = url.toString();

2. Im Callback – nachdem das Konto erstellt wurde – state dekodieren und den Lead senden:

// `state` kommt exakt so zurück, wie du es gesendet hast
const { clickId } = JSON.parse(atob(stateFromCallback));

await fetch("https://deine-app.de/api/lead", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    click_id: clickId,
    tag: "app_signup",
    firstname: profile.given_name,   // Microsoft: profile.givenName
    lastname:  profile.family_name,  // Microsoft: profile.surname
    email:     profile.email,        // Microsoft: profile.mail
  }),
});

Nutzt du state schon für CSRF?

Die meisten OAuth-Setups senden bereits ein zufälliges state zum Schutz vor CSRF – wirf es nicht weg. Speichere die Click-ID einfach daneben (wie im JSON oben) und validiere den CSRF-Teil wie gewohnt, wenn er zurückkommt.

Prüfen, ob es funktioniert

  1. Öffne deine App über einen getrackten Link (einen mit lj_*-Parametern, z. B. eine Test- Anzeigen-URL oder ein mit dem UTM Builder gebauter Link), damit eine Click-ID gespeichert wird. Bei Option 2 (Script nur auf der Root-Domain) landest du über den getrackten Link zuerst auf deiner Marketing-Seite, klickst dann in die App weiter – und prüfst, dass der click_id-Parameter beim Ankommen in der App-URL steht.
  2. Erstelle ein Testkonto – einmal über das Formular, einmal mit Google, einmal mit Microsoft.
  3. Unter Settings → Events steigt der Total-Zähler des Lead-Events und sein Status wechselt auf Active.
  4. Um einen einzelnen Aufruf zu prüfen (Statuscode, Payload, ob die Click-ID gematcht hat), öffne das API-Postbacks-Log.

Keine Click-ID? Trotzdem das Lead senden

Ein Besucher, der organisch oder direkt kam, hat keine Click-ID – clickId ist dann leer, und das ist okay. Sende das Lead trotzdem: LeadJourney matcht auch über die E-Mail, das Konto wird also erfasst und kann später zugeordnet werden, falls die Person vorher auf einen getrackten Link geklickt hat. Blockiere das Sign-up-Event nie nur, weil die Click-ID fehlt.

FAQ

Verwandte Artikel

Auf dieser Seite