Geo personalisierte Ads und Content: zeig jedem Besucher die Tatsachen, die dort stimmen, wo er ist

Kurz gesagt

Niveau: Fortgeschritten

Der Standort verändert ein paar echte Tatsachen: Lieferzeit und Versandkosten, ob der Laden nah ist, was vorrätig ist. Personalisiere diese, das Verkaufsargument bleibt gleich.

  • Trau zuerst der eigenen Postleitzahl der Kundin, der IP Adresse nur für Land und Bundesland.
  • Wähl in Google Ads bewusst zwischen Präsenz und Präsenz oder Interesse. Meta bietet nur noch Menschen, die dort wohnen oder kürzlich dort waren.
  • Lies den Standort bei jeder Anfrage aus dem Header deines Hosters und speichere nichts im Browser.
  • Beweise die Wirkung mit einer Kontrollgruppe, deren Größe vor dem Start feststeht.

Wo ein Besucher ist, verändert eine Handvoll echter Tatsachen, und eine Seite, die diese Tatsachen richtig zeigt, verkauft mehr als eine, die rät. In diesem Artikel zeige ich am Beispiel eines erfundenen Leipziger Outdoorladens, wie ich den Standort in Anzeigen, auf Landingpages und in Mails nutze: von der Frage, welcher Standortquelle du trauen kannst, über die Targeting Einstellungen der Werbeplattformen und die deutsche Rechtslage bis zum Test, der beweist, dass es gewirkt hat.

Der Standort ist eine Tatsache über den Besucher, keine Stimmung

Wenn über Geo Personalisierung geredet wird, klingt es oft nach Zaubertrick: Zeig dem Besucher seine Stadt, streu ein bisschen Dringlichkeit darüber und schau zu, wie die Zahlen steigen. Genau diese Sichtweise ist der Grund, warum so viel davon schiefgeht.

Wo jemand ist, verändert eine Handvoll echter Tatsachen. Wie schnell die Bestellung ankommt. Was der Versand kostet. Ob man heute Nachmittag noch in deinen Laden gehen kann. Ob die Veranstaltung, für die du wirbst, eine kurze Straßenbahnfahrt entfernt liegt oder fünf Stunden Autobahn. Wenn eine Seite jedem Besucher die Tatsachen zeigt, die für ihn stimmen, hilft sie. Wenn sie so tut, als wüsste sie mehr, als sie weiß, oder eine Dringlichkeit erfindet, die sie nicht einlösen kann, bewirkt sie das Gegenteil.

Mein Test ist deshalb einfach. Wäre die Seite falsch oder weniger nützlich, wenn sie allen dasselbe zeigt? Wenn ja, personalisiere nach Ort. Wenn nein, lass es bleiben, denn jede Variante, die du hinzufügst, musst du bauen, testen und ehrlich halten.

Alles in diesem Artikel ist meine eigene Arbeitsweise, und ich sage es auch so. Wo ich mich auf eine Tatsache von außen stütze, meist auf die Dokumentation der Werbeplattformen und auf deutsches und europäisches Recht, steht eine Fußnote. Das Unternehmen in den Beispielen ist erfunden.

Durchgerechnetes Beispiel: der Laden

Auwald Outdoor ist ein Laden für Outdoorbekleidung in Leipzig. Es gibt ihn nicht. Lena, die ihn führt, verkauft Regenjacken, Wanderschuhe und Funktionsunterwäsche online unter auwaldoutdoor.example und hat einen kleinen Laden nahe dem Hauptbahnhof, in dem sie auch Wanderschuhe anpasst. Ihre meistverkaufte Jacke kostet 140 €.

An einem Dienstagmorgen öffnen drei Menschen die Seite dieser Jacke. Eine Person ist in Leipzig. Eine in Stuttgart. Eine in Westerland auf Sylt. Für die Person in Leipzig gilt: Lieferung am nächsten Werktag, oder heute im Laden abholen. Für die Person in Stuttgart braucht Lenas Paketdienst laut ihrem Vertrag drei Werktage und kostet 6,95 €. Für die Person auf Sylt dauert es zwei Werktage.

Eine einzige Seite, auf der "Kostenloser Versand, morgen bei dir" steht, stimmt für eine der drei und ist für die anderen zwei still und leise falsch. Genau dieses Problem löst Geo Personalisierung. Nicht Raffinesse. Genauigkeit.

Woher der Standort kommt und wie weit du ihm trauen kannst

Bevor du irgendetwas personalisierst, sei ehrlich, woher der Standort stammt. Es gibt vier Quellen, und sie sind nicht gleich gut.

Am besten ist, was die Kundin dir selbst gesagt hat: eine Postleitzahl, eingetippt in eine Lieferzeitabfrage, oder die Adresse, die in ihrem Kundenkonto gespeichert ist. Sie ist genau, und die Kundin hat sie freiwillig angegeben.

An zweiter Stelle steht der Standort des Browsers aus der Geolocation API. Er ist präzise, aber der Browser fragt den Besucher vorher um Erlaubnis, und die Funktion steht nur auf sicheren Seiten (HTTPS) zur Verfügung.1 In einem Shop frage ich danach fast nie.

Drittens die IP Adresse. Dein Hoster oder dein CDN schlägt die Netzadresse des Besuchers in einer Datenbank nach und liefert eine bestmögliche Schätzung. Den Besucher kostet das nichts, es erscheint kein Hinweisfenster, und deshalb greifen alle danach. Es ist aber auch die schwächste der drei Quellen. MaxMind, einer der großen Anbieter solcher Datenbanken, veröffentlicht eigene Genauigkeitszahlen: Für Deutschland landen 72 % der IP Adressen innerhalb von 50 km um den echten Standort, 27 % werden einer Stadt zugeordnet, die weiter weg liegt, und 1 % bekommt gar keine Stadt.2 Mobilfunknetze, Firmennetze und VPN Dienste machen das Bild noch unschärfer.

Viertens gar nichts. Manche Anfragen kommen ohne brauchbaren Standort an. Cloudflare zum Beispiel kennzeichnet sie mit dem besonderen Ländercode XX, und Besucher aus dem Tor Netzwerk mit T1.3 Deine Seite braucht für sie eine vernünftige Standardansicht.

Welchem Standort du trauen kannstEin Ablauf von oben nach unten für die Wahl der Standortquelle. Zuerst prüfen, ob die Kundin eine Postleitzahl angegeben hat oder eine gespeicherte Adresse hat. Wenn ja, diese nutzen. Wenn nein, prüfen, ob die IP Abfrage ein Land geliefert hat. Wenn ja, nur auf Ebene des Landes oder Bundeslands personalisieren und die Postleitzahlabfrage anbieten. Wenn nein, die Standardseite mit der Postleitzahlabfrage zeigen.Ein Besucher öffnet die SeitePostleitzahl angegeben oder Adressegespeichert?jaNutzen: genaue Lieferzusage, nächsterLaden, Bestand vor OrtneinHat die IP Abfrage ein Landgeliefert?jaNur nach Land oder Bundeslandpersonalisieren und diePostleitzahlabfrage anbietenneinStandardseite mit Postleitzahlabfragezeigen

Lies es von oben. Die eigene Postleitzahl der Kundin gewinnt immer, wenn du sie hast. Die IP Abfrage ist die Rückfallebene, und ihr traust du nur die grobe Entscheidung zu: welches Land, welches Bundesland. Alles, was feiner ist, fragt die Seite ab.

Durchgerechnetes Beispiel: Lenas Besucher in einem Monat

Lena schaut sich einen Monat Verkehr auf ihren Produktseiten an: 10.000 Besucher. Davon sind 1.800 mit einer gespeicherten Adresse angemeldet. Weitere 600 tippen ihre Postleitzahl in die Lieferzeitabfrage auf der Seite. Bleiben 7.600, die ihr nichts verraten haben, und bei 300 davon liefert die IP Abfrage nicht einmal ein Land.

Für 7.300 Besucher ist die IP Adresse also der einzige Hinweis. Würde Lena damit eine Zusage auf Ebene der Stadt machen, läge sie nach MaxMinds eigenen Zahlen für Deutschland bei gut einem Viertel falsch oder ins Leere:

7.300×(0,27+0,01)=2.0447.300 \times (0{,}27 + 0{,}01) = 2.044

Dabei ist 7.3007.300 die Zahl der Besucher, die nur über die IP verortet werden, 0,270{,}27 der Anteil, der einer falschen Stadt (mehr als 50 km entfernt) zugeordnet wird, und 0,010{,}01 der Anteil ganz ohne Stadt. Etwa 2.0442.044 Besucher im Monat würden also eine Zusage für ihre Stadt sehen, die nicht zu ihnen passt. Deshalb nutzt Lena die IP nur, um das Bundesland zu erkennen, und setzt für alles Feinere eine Postleitzahlabfrage direkt neben die Lieferzeile.

Den Standort am Rand lesen, ohne ihn zu speichern

Die meisten modernen Hoster erledigen die IP Abfrage bereits für dich und reichen das Ergebnis als Request Header an deinen Code weiter. Du brauchst keine eigene Datenbank und keine Bibliothek, die Adressen zerlegt.

Bei Vercel kommt das Land in x-vercel-ip-country als zweistelliger ISO Code an, und x-vercel-ip-country-region trägt die Region der ersten Ebene. Vercels Dokumentation erklärt das am britischen Beispiel: Dort ist diese Region ein Landesteil wie England, nicht eine Grafschaft wie Devon.4 Die erste Ebene unterhalb des Staates ist in Deutschland das Bundesland, Vercel liefert also Kürzel wie SN für Sachsen oder BY für Bayern. Genau diese Auflösung braucht Lena. Bei Cloudflare kommt das Land im Header CF-IPCountry an.3 Wer dort auch die Region will, schaltet die verwaltete Transformation "Add visitor location headers" ein, die unter anderem cf-region-code mitschickt.5

Zwei Korrekturen an Code, der dir in älteren Anleitungen noch begegnen wird, auch in einer älteren Fassung dieses Artikels. Erstens hat Next.js mit Version 15 die Eigenschaften geo und ip aus seinem Request Objekt entfernt, weil diese Werte vom Hoster kommen und nicht vom Framework.6 Zweitens heißt die Datei, die vor jeder Anfrage läuft und lange Middleware hieß, ab Next.js 16 Proxy.7 Und lies die Adresse des Besuchers nicht auf eigene Faust aus x-forwarded-for: Hinter einem Proxy kann dort eine ganze Liste von Adressen stehen, und Cloudflare empfiehlt genau deshalb seinen eigenen Header CF-Connecting-IP.3

Die dritte Korrektur ist meine eigene, und sie wiegt schwerer als die beiden anderen. Die alte Fassung hat das Land des Besuchers in einem Cookie gespeichert. Das musst du nicht. Der Header kommt mit jeder Anfrage, die Seite kann also jedes Mal neu entscheiden und nichts im Browser des Besuchers ablegen. Damit fällt eine ganze Gruppe von Einwilligungsfragen weg, und darauf komme ich im Abschnitt zum Recht zurück.

Durchgerechnetes Beispiel: Lenas Proxy Datei

Lenas Website läuft mit Next.js auf Vercel. Ihr Proxy liest das Bundesland aus dem Header, ordnet es einem ihrer vier Liefergebiete zu und gibt das Ergebnis als Request Header an die Seite weiter, damit die richtige Lieferzeile schon auf dem Server entsteht. Im Browser wird nichts gespeichert.

Die Liefergebiete stammen aus Lenas Versandverträgen: Mitteldeutschland (SN, ST, TH), der Norden (SH, NI, HH, HB, MV), der Südwesten (BW, RP, SL) und die übrigen Länder (BE, BB, BY, HE, NW).

// proxy.js
import { NextResponse } from 'next/server'

// Liefergebiete nach Bundesland, laut Lenas Versandverträgen
const ZONES = {
  SN: 'MITTE', ST: 'MITTE', TH: 'MITTE',
  SH: 'NORD', NI: 'NORD', HH: 'NORD', HB: 'NORD', MV: 'NORD',
  BW: 'SUEDWEST', RP: 'SUEDWEST', SL: 'SUEDWEST',
  BE: 'REST', BB: 'REST', BY: 'REST', HE: 'REST', NW: 'REST',
}

export function proxy(request) {
  const country = request.headers.get('x-vercel-ip-country') || ''
  const region = request.headers.get('x-vercel-ip-country-region') || ''

  // Der IP nur eine grobe Entscheidung anvertrauen: welches Liefergebiet, oder keines.
  const zone = country === 'DE' && Object.hasOwn(ZONES, region) ? ZONES[region] : 'UNKNOWN'

  const headers = new Headers(request.headers)
  headers.set('x-auwald-zone', zone)
  return NextResponse.next({ request: { headers } })
}

export const config = { matcher: ['/products/:path*'] }

Schritt für Schritt. Ein Besucher in einem Leipziger Mobilfunknetz kommt mit dem Land DE und der Region SN an, die Seite erhält MITTE und zeigt "Morgen bei dir in fast ganz Deutschland, oder heute in Leipzig abholen". Eine Besucherin in Stuttgart kommt mit BW an, die Seite erhält SUEDWEST und zeigt "Drei Werktage in den Südwesten, 6,95 €". Ein Besucher mit einem VPN, das in den Niederlanden endet, kommt mit NL an, die Seite erhält UNKNOWN und zeigt die neutrale Zeile mit der Postleitzahlabfrage. Liefe Lenas Shop stattdessen mit Rails hinter Cloudflare, stünde dieselbe Entscheidung in einem Controller und läse request.headers['CF-IPCountry'] und request.headers['cf-region-code'].

In der Anzeige: entscheide, wer als "dort" zählt

Beim Standorttargeting der Werbeplattformen gibt es eine Einstellung, die mehr entscheidet als jede andere, und die meisten Konten schauen sie nie an.

In Google Ads wählst du zwischen zwei Optionen. "Präsenz oder Interesse" ist die Voreinstellung und die, die Google empfiehlt. Sie erreicht Menschen, die sich wahrscheinlich in deinem Zielgebiet befinden oder regelmäßig dort sind, und dazu Menschen, die Interesse an diesem Gebiet gezeigt haben. "Präsenz" erreicht nur Menschen, die dort sind oder regelmäßig dort sind.8 Das Interesse leitet Google aus Signalen ab, etwa aus Begriffen in Suchanfragen oder aus Inhalten, die sich jemand über einen Ort angesehen hat.8 Google sagt offen, dass all das eine bestmögliche Schätzung ist und keine hundertprozentig genauen Ergebnisse garantiert sind.9

Du kannst ganze Länder auswählen, Regionen, Städte, je nach Land Postleitzahlen, oder einen Umkreis um eine Adresse, und dieser Umkreis muss mindestens 1 km betragen.9

Meta hat diese Wahl für dich getroffen. In der Targeting Referenz steht, dass der Standorttyp ['home', 'recent'] die einzige verfügbare Option ist, also Menschen, die in dem Gebiet wohnen oder kürzlich dort waren.10 Die Optionen, nur Anwohner oder nur Durchreisende anzusprechen, gibt es nicht mehr. Ein Umkreis um eine Stadt reicht von 17 bis 80 km, um einen eigenen Punkt wie deinen Laden von 1 bis 80 km.10

Welche Einstellung du brauchst, hängt an einer Frage. Muss die Person für dein Angebot körperlich vor Ort sein? Ein Onlineshop, der in ganz Deutschland liefert, kommt mit "Präsenz oder Interesse" gut zurecht. Eine Schuhanpassung, eine Veranstaltung im Laden oder eine Zusage für Lieferung am selben Tag nicht.

Durchgerechnetes Beispiel: die Kampagne für die Schuhanpassung

Lena gibt im Monat 1.200 € für eine Google Ads Kampagne aus, die für die Schuhanpassung in ihrem Leipziger Laden wirbt. Sie zielt auf einen Umkreis von 15 km um den Laden, mit der Voreinstellung "Präsenz oder Interesse". Im Monat bringt sie 800 Klicks zu je 1,50 €.

Der Standortbericht zeigt, dass 220 dieser Klicks von Menschen kamen, die sich gar nicht im Großraum Leipzig befanden, vor allem aus Hamburg, wo Leute vor einem Wochenende in Leipzig mit Abstecher in die Sächsische Schweiz nach Wanderschuhen in Leipzig suchen. Zur Anpassung kommen sie nicht. Der Anteil der Klicks, die außerhalb des Gebiets ausgegeben wurden, ist eine einfache Rate:

Anteilaußen=Klicks von außerhalb des Gebietsalle Klicks\text{Anteil}_{\text{außen}} = \frac{\text{Klicks von außerhalb des Gebiets}}{\text{alle Klicks}}

Dabei ist Anteilaußen\text{Anteil}_{\text{außen}} der Bruchteil der bezahlten Klicks, die von Menschen außerhalb des Zielgebiets kamen, der Zähler zählt diese Klicks, und der Nenner zählt alle Klicks im selben Zeitraum. Es ist ein Verhältnis von Ereignissen zu Gelegenheiten, von Grund auf erklärt in Grundlagen: Verhältnisse und Raten.

Anteilaußen=220800=0,275\text{Anteil}_{\text{außen}} = \frac{220}{800} = 0{,}275

Also haben 27,5 % der Klicks, 220×1,50 €=330 €220 \times 1{,}50\ \text{€} = 330\ \text{€} im Monat, Menschen bezahlt, die das Angebot gar nicht nutzen konnten. Lena stellt die Kampagne für die Schuhanpassung auf "Präsenz" um und lässt "Präsenz oder Interesse" in ihren Kampagnen für den Onlineshop, denn eine Besucherin aus Hamburg, die für genau diese Tour eine Jacke kauft, ist dort genau die Richtige.

Für den Tauschabend für gebrauchte Ausrüstung im Laden schaltet sie eine Meta Anzeige mit einem eigenen Standort direkt auf dem Laden und 10 km Umkreis. Sie nimmt hin, dass "kürzlich dort" auch ein paar Gäste der Stadt erreicht, weil Meta sie nicht mehr ausschließen lässt, und schreibt Datum und Adresse in die erste Zeile der Anzeige, damit niemand aus Versehen anreist.

Im Anzeigentext: nenn den Ort nur, wo die Zusage stimmt

Google kann den Ort für dich in die Anzeige einsetzen. Mit dem Standortplatzhalter in responsiven Suchanzeigen tippst du beim Schreiben eine geschweifte Klammer, wählst den Standortplatzhalter aus, und Google setzt Stadt, Bundesland oder Land aus dem Standorttargeting deiner Kampagne ein, mit einem Standardtext für den Fall, dass kein Ort eingesetzt werden kann.11 In einen Anzeigentitel passt ein Standort, in die Beschreibungen bis zu zwei.11

Das schneidet in beide Richtungen. Die Anzeige behauptet jetzt etwas über diesen Ort, und wenn die Zusage dort nicht stimmt, hast du mit demselben Euro einen Klick und eine Enttäuschung gekauft.

Durchgerechnetes Beispiel: der Titel, der beinahe getäuscht hätte

Lenas Kampagne für den Onlineshop zielt auf Leipzig, Halle, Dresden und Zwickau. Ihr erster Entwurf für einen Titel mit Standortplatzhalter lautet "Schuhanpassung in [Stadt]". In Halle hieße das "Schuhanpassung in Halle". In Halle gibt es keine Schuhanpassung. Der Laden ist in Leipzig.

Sie schreibt den Titel um eine Zusage herum, die an jedem Zielort stimmt: "Wanderschuhe morgen in [Stadt]", mit dem Standardtext "Wanderschuhe, morgen bei dir". Lieferung am nächsten Werktag gilt für alle vier Städte, der Ortsname macht die Anzeige also relevanter, ohne eine Lüge hineinzutragen. Die Schuhanpassung bekommt eine eigene Anzeige in der Kampagne nur für Leipzig, und dort steht "in Leipzig" einfach ausgeschrieben. Die Landingpage wiederholt die Zusage mit denselben Worten, denn Anzeige und Seite müssen übereinstimmen, sonst spürt der Besucher den Bruch.

Auf der Landingpage: die Tatsachen ändern, das Verkaufsargument behalten

Auf der Seite verdient der Standort sein Geld. Meine Regel: Das Verkaufsargument bleibt überall gleich, die Tatsachen ändern sich. Das Produkt, die Fotos, die Gründe zum Kaufen sind für Leipzig und Stuttgart identisch. Was sich ändert, sind die Lieferzusage, die Versandkosten, ob der Laden nah genug für einen Besuch ist, und ob ein Artikel dort vorrätig ist, von wo er verschickt wird.

Die Zahl, auf die du schauen solltest, ist die Conversion Rate für jede Region für sich, nie der Durchschnitt der ganzen Website. Der Durchschnitt wird von der Gegend bestimmt, aus der die meisten deiner Besucher kommen, und er versteckt eine Region, die still und leise scheitert.

CRr=Bestellungen aus Region rBesucher aus Region r\text{CR}_{r} = \frac{\text{Bestellungen aus Region } r}{\text{Besucher aus Region } r}

Dabei ist CRr\text{CR}_{r} die Conversion Rate für eine Region rr, der Zähler ist die Zahl der Bestellungen von Besuchern aus dieser Region im Zeitraum, und der Nenner ist die Zahl der Besucher aus dieser Region im selben Zeitraum. Wie der Klickanteil oben ruht sie auf Grundlagen: Verhältnisse und Raten, und die Warnung von dort gilt auch hier: Eine Rate aus einer kleinen Region mit wenigen Besuchern schwankt von Monat zu Monat stark.

Durchgerechnetes Beispiel: die Lücke im Südwesten

Lena teilt drei Monate Bestellungen nach ihren vier Liefergebieten auf. Für Bestellungen nimmt sie das Bundesland der Lieferadresse, für Besucher, die nicht gekauft haben, das Bundesland aus der IP.

Conversion Rate nach LiefergebietEin Balkendiagramm der Conversion Rate von Auwald Outdoor nach Liefergebiet über drei Monate, vor jeder Änderung am Standort. Mitteldeutschland 2,6 %, übrige Länder 2,4 %, Norden 1,9 %, Südwesten 0,9 %.Auwald Outdoor, Conversion Rate nach Liefergebiet vor der Änderung0 %1,3 %2,5 %3,8 %5 %2,6 %Mitteldeutschland2,4 %Übrige Länder1,9 %Norden0,9 %SüdwestenConversion Rate in %Liefergebiet des Besuchers, nach Bundesland

Die waagrechte Achse zeigt das Liefergebiet des Besuchers, gebildet aus seinem Bundesland. Die senkrechte Achse zeigt die Conversion Rate in Prozent, Bestellungen geteilt durch Besucher, für jedes Gebiet für sich. Die Erkenntnis: Der Südwesten konvertiert mit etwa einem Drittel der Rate von Mitteldeutschland, und der Norden mit weniger als drei Vierteln davon.

Nimm den Südwesten. In den drei Monaten 4.000 Besucher und 36 Bestellungen: CRSW=364.000=0,009\text{CR}_{\text{SW}} = \frac{36}{4.000} = 0{,}009, also 0,9 %. Lena geht den Checkout als Kundin aus Stuttgart durch und findet das Leck sofort. Die Produktseite sagt "Kostenloser Versand, morgen bei dir". Der Checkout rechnet dann 6,95 € und drei Werktage dazu. Genau an dieser Stelle springen die Leute ab.

Die Lösung ist kein Trick. Die Produktseite zeigt für den Südwesten jetzt schon auf dem ersten Bildschirm die wahre Zeile, "Drei Werktage in den Südwesten, 6,95 €, ab 150 € kostenlos", und der Checkout sagt dasselbe. Für den Norden, wo die IP Kiel nicht von Sylt unterscheiden kann, zeigt die Seite "Morgen bei dir in fast ganz Norddeutschland" und gleich daneben die Postleitzahlabfrage. Lena nimmt nicht einfach an, dass das wirkt. Sie testet es, und das ist der nächste Gedanke.

Beweis durch eine Kontrollgruppe, nicht durch eine Geschichte

Personalisierung ist eine Änderung an der Seite, also wird sie getestet wie jede andere Änderung. Am saubersten geht das mit einer Kontrollgruppe: Eine zufällige Hälfte der infrage kommenden Besucher sieht weiter die alte Seite, die andere Hälfte die personalisierte, und du vergleichst beide über dieselben Wochen. Diesen Monat mit dem letzten zu vergleichen sagt dir nichts, denn Wetter, Saison und Werbebudget haben sich ebenfalls bewegt.

Lege die Größe des Tests fest, bevor du beginnst, und zwar anhand der kleinsten Verbesserung, die dir etwas bedeuten würde. Die Formel für einen Test zwischen zwei Conversion Rates lautet:

n=(zα/2+zβ)2[p1(1−p1)+p2(1−p2)](p1−p2)2n = \frac{(z_{\alpha/2} + z_{\beta})^2 \left[p_1(1-p_1) + p_2(1-p_2)\right]}{(p_1 - p_2)^2}

Dabei ist nn die Zahl der Besucher, die du in jeder Hälfte des Tests brauchst, zα/2z_{\alpha/2} ist 1,96 für ein Signifikanzniveau von 5 %, zβz_{\beta} ist 0,84 für eine Teststärke von 80 % (eine Chance von 80 %, eine echte Verbesserung der gewählten Größe zu entdecken), p1p_1 ist die Conversion Rate, die du ohne die Änderung erwartest, und p2p_2 die Rate, die du dir mit ihr erhoffst. Die vollständige Herleitung und was jede Wahl bedeutet, stehen in Grundlagen: Stichprobengröße.

Wenn der Test vorbei ist, ist das Ergebnis eine relative Veränderung von der alten Rate zur neuen:

Δ%=vneu−valtvalt×100\Delta\% = \frac{v_{\text{neu}} - v_{\text{alt}}}{v_{\text{alt}}} \times 100

Dabei ist Δ%\Delta\% die relative Veränderung, vneuv_{\text{neu}} die Conversion Rate mit Personalisierung und valtv_{\text{alt}} die Rate ohne. Halte das auseinander von der Veränderung in Prozentpunkten, die einfach vneu−valtv_{\text{neu}} - v_{\text{alt}} ist. Den Unterschied zwischen beiden erkläre ich in Grundlagen: Prozente.

Und um eine echte Verbesserung von Zufall zu unterscheiden, ein Test für zwei Anteile:

z=p1−p2p(1−p)(1n1+1n2)z = \frac{p_1 - p_2}{\sqrt{p(1-p)\left(\frac{1}{n_1} + \frac{1}{n_2}\right)}}

Dabei ist zz die Teststatistik, p1p_1 und p2p_2 sind die beiden beobachteten Conversion Rates, pp ist die gemeinsame Rate über beide Hälften, und n1n_1 und n2n_2 sind die Besucher in jeder Hälfte. Liegt zz weiter als 1,96 von null entfernt, ist der Unterschied auf dem Niveau von 5 % signifikant. Die Begründung steht in Grundlagen: Hypothesentests.

Durchgerechnetes Beispiel: Lenas Test über sechs Wochen

Der Südwesten allein ist zu klein für einen Test, also testet Lena das ganze Paket standortgerechter Lieferzeilen über alle Besucher, die die IP einem Bundesland zuordnet. Ihre aktuelle Rate liegt bei 2,0 %. Handeln würde sie bei einer Steigerung auf 2,4 %. Mit 1,96 und 0,84 ergibt die erste Klammer (1,96+0,84)2=7,84(1{,}96 + 0{,}84)^2 = 7{,}84, und der Varianzterm ist 0,020×0,980+0,024×0,976=0,0430240{,}020 \times 0{,}980 + 0{,}024 \times 0{,}976 = 0{,}043024. Der Abstand, den sie entdecken will, ist 0,024−0,020=0,0040{,}024 - 0{,}020 = 0{,}004. Zusammengesetzt:

n=7,84×0,0430240,0042=0,337310,000016=21.082n = \frac{7{,}84 \times 0{,}043024}{0{,}004^2} = \frac{0{,}33731}{0{,}000016} = 21.082

Sie braucht etwa n=21.082n = 21.082 Besucher in jeder Hälfte, 42.164 insgesamt. Bei 30.000 infrage kommenden Besuchern im Monat sind das etwas mehr als sechs Wochen, also legt sie das Enddatum fest, bevor sie startet, und schaut zwischendurch nicht nach.

Am Ende hat die alte Seite 422 von 21.100 Besuchern zu Käufern gemacht (2,0 %) und die personalisierte 485 von 21.100 (etwa 2,3 %). Die relative Steigerung:

Δ%=2,3−2,02,0×100=15\Delta\% = \frac{2{,}3 - 2{,}0}{2{,}0} \times 100 = 15

Also 15 % relative Steigerung, oder 0,3 Prozentpunkte. Ist das Zufall? Die gemeinsame Rate ist p=422+48542.200=0,0215p = \frac{422 + 485}{42.200} = 0{,}0215, und damit:

z=0,023−0,0200,0215×0,9785×221.100=0,0030,001412=2,12z = \frac{0{,}023 - 0{,}020}{\sqrt{0{,}0215 \times 0{,}9785 \times \frac{2}{21.100}}} = \frac{0{,}003}{0{,}001412} = 2{,}12

Mit z=2,12z = 2{,}12, also jenseits von 1,96, ist die Steigerung auf dem Niveau von 5 % signifikant (der zweiseitige p Wert liegt bei etwa 0,03). Sie ist kleiner als die erhofften 2,4 % und trotzdem klar wert, sie zu behalten. Achte darauf, was Lena nicht tut: die beste Woche einer einzelnen Region als Schlagzeile zitieren. Eine große Zahl aus einem Test in einer Saison ist eine Geschichte. Die Kontrollgruppe ist der Beweis.

In der Mail: nimm die Adresse, die du schon hast

In der Mail ist der Standort am leichtesten richtig zu treffen, und genau dort geht er am häufigsten schief. Viele greifen zur IP Adresse der letzten Mailöffnung, und das kann ein Firmennetz sein, ein Handy im ICE oder der Bildproxy eines Mailanbieters. Gleichzeitig liegt die Lieferadresse der Kundin in der Bestellhistorie, genau und freiwillig angegeben.

Deshalb personalisiere ich Mails nach der letzten Lieferadresse und nach nichts anderem. Jede Mailplattform mit bedingten Blöcken kann das, und wenn die Mail auf deinem eigenen Server entsteht, sind es ein paar Zeilen Code.

Durchgerechnetes Beispiel: die Mail zu Winterschuhen

Lena verschickt im November eine Mail zu Winterschuhen. Die Zeile zur Lieferung muss für jede Kundin stimmen, und die Bedingungen ihres Paketdienstes ergeben drei Gruppen: den Südwesten, den ihr Vertrag über die ersten beiden Ziffern der Postleitzahl festlegt (die Leitregionen 54 bis 56 und 66 bis 79), die Inselpostleitzahlen auf der Zuschlagsliste ihres Paketdienstes und den Rest von Deutschland. Die Leitregionen decken sich nicht genau mit den Ländergrenzen, und genau deshalb zählt in der Mail die Postleitzahl und auf der Seite nur die grobe Schätzung mit der Abfrage daneben. Ihr Shop läuft mit Rails, also wählt die Mail die Zeile aus der gespeicherten Adresse:

class DeliveryPromise
  # Leitregionen und Inselpostleitzahlen laut Lenas eigenem Vertrag mit dem Paketdienst
  SOUTHWEST = [54..56, 66..79].freeze
  ISLANDS = %w[25980 25938 26548 26571 26757 27498 18565].freeze

  def self.for(postcode)
    plz = postcode.to_s.strip[/\A\d{5}\z/]
    return "Kostenloser Versand ab 75 € in fast ganz Deutschland" unless plz
    return "Drei Werktage in den Südwesten, 6,95 €, ab 150 € kostenlos" if SOUTHWEST.any? { |range| range.cover?(plz[0, 2].to_i) }
    return "Zwei Werktage zu dir, ab 75 € kostenlos" if ISLANDS.include?(plz)

    "Lieferung am nächsten Werktag, ab 75 € kostenlos"
  end
end

Schritt für Schritt. Eine Kundin mit der Postleitzahl 04109 hat die Leitregion 04, die nicht zum Südwesten gehört, und 04109 steht nicht auf der Inselliste, also sagt die Mail "Lieferung am nächsten Werktag, ab 75 € kostenlos". Ein Kunde in Westerland mit 25980 steht auf der Inselliste, also nennt die Mail zwei Werktage. Eine Kundin in Stuttgart mit 70173 hat die Leitregion 70 und bekommt die Zeile für den Südwesten. Ein Newsletter Abonnent, der nie bestellt hat, hat keine Postleitzahl, also fällt die Mail auf die neutrale Zeile zurück, statt zu raten, wo er die letzte geöffnet hat. Lena pflegt beide Listen an einer Stelle, in derselben Datei, die auch ihre Produktseite nutzt, damit sich Mail und Seite nie widersprechen.

Das Recht: was Standortdaten in Deutschland bedeuten

Nichts davon ist Rechtsberatung, und wenn echtes Risiko im Spiel ist, frage ich eine Anwältin oder einen Anwalt. Drei Punkte prägen aber, wie ich es baue, und jeder stammt aus dem Gesetz selbst, aus der Rechtsprechung oder von den Aufsichtsbehörden.

Erstens ist eine IP Adresse ein personenbezogenes Datum. Der Europäische Gerichtshof hat 2016 im Fall Breyer (Rechtssache C 582/14) entschieden, dass selbst eine dynamische IP Adresse, die ein Websitebetreiber beim Besuch seiner Seite speichert, für ihn ein personenbezogenes Datum ist, wenn er rechtliche Mittel hat, die Person mit Zusatzwissen des Zugangsanbieters bestimmen zu lassen.12 Die DSGVO nennt in ihrer Begriffsbestimmung in Art. 4 Nr. 1 ausdrücklich Standortdaten und Online Kennungen, und ihr Erwägungsgrund 30 nennt IP Adressen und Cookie Kennungen als Beispiele.13 Wer eine IP nachschlägt, auch nur für einen Augenblick, verarbeitet also personenbezogene Daten. Dafür braucht es eine Rechtsgrundlage nach Art. 6 DSGVO und einen Satz in der Datenschutzerklärung, und es ist ein guter Grund, die IP für eine einzige grobe Entscheidung zu nutzen und sie dann wieder loszulassen.

Zweitens ist die Vorschrift zu Standortdaten im Telekommunikation Digitale Dienste Datenschutz Gesetz (TDDDG) enger, als viele denken. § 13 TDDDG regelt Standortdaten von Nutzern öffentlicher Telekommunikationsnetze und Telekommunikationsdienste und erlaubt ihre Verarbeitung für einen Dienst mit Zusatznutzen nur, wenn sie anonymisiert sind oder die Person nach Information eingewilligt hat.14 Gemeint sind Daten, die beim Netzbetrieb über den Ort eines Endgeräts entstehen, etwa die Ortung eines Handys über die Funkzellen. Ein Shop, der aus einem IP Header das Bundesland schätzt, ist kein Telekommunikationsanbieter, und § 13 TDDDG ist deshalb nicht die Regel, die für ihn gilt. Für ihn gilt die DSGVO.

Drittens hat das Speichern im Browser des Besuchers seine eigene Regel. Nach § 25 TDDDG braucht jedes Speichern von Informationen auf dem Endgerät und jedes Auslesen dort eine Einwilligung, außer es ist unbedingt erforderlich, damit der Anbieter einen vom Nutzer ausdrücklich gewünschten digitalen Dienst zur Verfügung stellen kann.15 Die Datenschutzkonferenz von Bund und Ländern legt dieses "unbedingt erforderlich" streng aus: Gemeint ist technische Erforderlichkeit für genau den gewünschten Dienst, und wirtschaftlicher Nutzen für das Geschäftsmodell reicht nicht.16 Ein Cookie, das sich das geschätzte Bundesland merkt, ist bequem, aber technisch nicht erforderlich. Wer wie Lenas Proxy bei jeder Anfrage neu aus dem Header entscheidet, umgeht die Frage ganz.

Durchgerechnetes Beispiel: Lenas Prüfung in drei Zeilen

Vor dem Start prüft Lena drei Dinge. Ihre Datenschutzerklärung sagt jetzt in klaren Worten, dass die Website die IP Adresse des Besuchers nutzt, um sein Bundesland zu schätzen und daraus die passende Lieferinformation zu zeigen, und dass diese Schätzung nicht gespeichert wird. Ihr Proxy schreibt kein Cookie und protokolliert keinen Standort. Und die Standortabfrage des Browsers erscheint nie, weil sie die Geolocation API nicht aufruft. Wollte sie eines Tages einen Knopf "Händler in meiner Nähe finden", würde sie die Abfrage erst auslösen, wenn der Besucher den Knopf drückt, nie beim Laden der Seite.

Für die größere Frage, wie weit Personalisierung gehen darf, bevor sie aufhört, sich hilfreich anzufühlen, komme ich immer wieder auf die Geschichte in die Ethikgrenze der Personalisierung zurück.

Womit du am Montag anfängst

Dafür brauchst du keine Personalisierungsplattform. Du brauchst eine kurze Liste von Tatsachen, die sich wirklich von Ort zu Ort unterscheiden.

Fang mit der Lieferzusage an, denn sie ist die Tatsache, die heute am ehesten für irgendwen falsch ist. Teil deine Conversion Rate nach Bundesland oder Liefergebiet auf und such nach dem Gebiet, das still und leise scheitert. Stell die Standortoption der Werbeplattformen bewusst ein, Kampagne für Kampagne, mit der Frage, ob die Person für das Angebot vor Ort sein muss. Setz den Ortsnamen nur dann in eine Anzeige, wenn die Zusage an jedem Ort stimmt, an dem er eingesetzt wird. Nutze die eigene Postleitzahl der Kundin, wo immer du sie hast, und die IP Adresse nur für die grobe Entscheidung. Speichere nichts, was du nicht brauchst. Und teste das Ganze mit einer Kontrollgruppe, deren Größe du festlegst, bevor du beginnst.

Über Grenzen hinweg zu verkaufen, mit anderen Währungen, Sprachen und Steuerregeln, ist eine größere Aufgabe mit eigenen Fallen, und darum geht es in Cross Border PPC und internationales Skalieren. Wie du eine neue Stadt von null an erschließt, steht in lokales Marktwachstum ohne großes Budget.

Footnotes

  1. MDN contributors, Geolocation API, MDN Web Docs, Mozilla, deutsche Fassung, https://developer.mozilla.org/de/docs/Web/API/Geolocation_API

  2. MaxMind, GeoIP Accuracy Comparison, Werte für Deutschland, MaxMind, https://www.maxmind.com/en/geoip-accuracy-comparison

  3. Cloudflare, Cloudflare HTTP headers, Cloudflare documentation, https://developers.cloudflare.com/fundamentals/reference/http-headers/

  4. Vercel, Request headers, Vercel documentation, 2025, https://vercel.com/docs/headers/request-headers

  5. Cloudflare, Managed Transforms reference, Add visitor location headers, Cloudflare documentation, https://developers.cloudflare.com/rules/transform/managed-transforms/reference/

  6. Vercel, How to upgrade to version 15, Next.js documentation, https://nextjs.org/docs/app/guides/upgrading/version-15

  7. Vercel, proxy.js file convention, Next.js documentation, https://nextjs.org/docs/app/api-reference/file-conventions/proxy

  8. Google, Erweiterte Standortoptionen, Google Ads Hilfe, https://support.google.com/google-ads/answer/1722038?hl=de

  9. Google, Targeting auf Standorte, Google Ads Hilfe, https://support.google.com/google-ads/answer/1722043?hl=de

  10. Meta, Basic Targeting, Marketing API documentation, Meta for Developers, https://developers.facebook.com/docs/marketing-api/audiences/reference/basic-targeting

  11. Google, Standortplatzhalter in responsiven Suchanzeigen, Google Ads Hilfe, https://support.google.com/google-ads/answer/9773001?hl=de

  12. Gerichtshof der Europäischen Union, Urteil vom 19. Oktober 2016, Patrick Breyer gegen Bundesrepublik Deutschland, Rechtssache C-582/14, ECLI:EU:C:2016:779, EUR-Lex, https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=CELEX:62014CJ0582

  13. Europäisches Parlament und Rat, Verordnung (EU) 2016/679 (Datenschutz Grundverordnung), Art. 4 Nr. 1 und Erwägungsgrund 30, EUR-Lex, https://eur-lex.europa.eu/legal-content/DE/TXT/?uri=CELEX:32016R0679

  14. Bundesministerium der Justiz, § 13 TDDDG Standortdaten, Gesetze im Internet, https://www.gesetze-im-internet.de/ttdsg/__13.html

  15. Bundesministerium der Justiz, § 25 TDDDG Schutz der Privatsphäre bei Endeinrichtungen, Gesetze im Internet, https://www.gesetze-im-internet.de/ttdsg/__25.html

  16. Konferenz der unabhängigen Datenschutzaufsichtsbehörden des Bundes und der Länder, Orientierungshilfe der Aufsichtsbehörden für Anbieter:innen von digitalen Diensten (OH Digitale Dienste), Version 1.2, November 2024, Randnummer 78, https://www.datenschutzkonferenz-online.de/media/oh/OH_Digitale_Dienste.pdf

Wenn deine Lieferzusage für manche Kunden stimmt und für andere nicht, schauen wir sie uns gern in einem kostenlosen Workshop gemeinsam an. Die ersten zwei Wochen Arbeit gehen auf meine Rechnung.