Alle denken das falsch herum. Einen SHA-256-Digest zu erzeugen kostet vier Zeilen Apps Script. Einen Match aus einer Werbeplattform zu holen kostet Normalisierung – und an der Normalisierung sterben Listen.
Google sagt es in der eigenen API-Dokumentation unmissverständlich: "If the contact information is not correctly formatted before hashing, the API still accepts the hashed information, but it can't be matched with a customer."
Der Upload gelingt. Was scheitert, ist die Match-Rate. Und nichts sagt es dir.
Dieser Leitfaden behandelt beide Hälften – wie du in Google Tabellen tatsächlich einen Hash erzeugst und welche plattformspezifischen Normalisierungsregeln darüber entscheiden, ob er irgendetwas trifft. Für die erste Hälfte gibt es vier Wege. Der kürzeste ist ein Add-on, das in einer Funktion normalisiert und hasht – Weg 1 weiter unten –, und der Rest dieser Seite ist die Begründung, warum die Normalisierung der Teil ist, den man richtig machen sollte.
Zuerst: Google Tabellen hat keine Hash-Funktion
Googles veröffentlichte Funktionsliste umfasst siebzehn Kategorien – Datum, Technisch, Finanzen, Text, Mathematik und so weiter. Es gibt kein SHA256, kein MD5, kein HASH, kein DIGEST. Die Kategorie Technisch enthält Basisumrechnungen und komplexe Zahlen und nichts Kryptografisches.
Jeder Weg ist also ein Umweg. Es gibt vier, und sie sind nicht gleich gut:
| Weg | Wann er passt | Urteil |
|---|---|---|
| Ein Add-on, das Hash-Funktionen in die Tabelle bringt | Du hast eine echte Kundenliste vorzubereiten und willst die Normalisierung erledigt haben | Empfohlen |
| Eigenes Apps Script als benutzerdefinierte Funktion | Du willst den Code besitzen oder brauchst einen Algorithmus bzw. eine Regel, die kein Add-on umsetzt | In Ordnung, mit Sorgfalt |
| Ein Web-Hasher | Du prüfst eine einzelne Testzeichenfolge | Nicht für eine Liste |
| Gar nicht hashen | Deine Plattform akzeptiert Klartext und deine Richtlinie erlaubt es | Legitim |
Der Rest dieses Abschnitts geht sie der Reihe nach durch. Die Normalisierungsregeln weiter unten gelten unabhängig davon, welchen Weg du wählst – sie entscheiden über deine Match-Rate, und kein Weg befreit dich von ihnen.
Weg 1: ein Add-on, das die Funktionen in die Tabelle bringt
Das ist der Weg, zu dem du greifen solltest, und der Grund ist genau das Argument dieser Seite. Einen Digest zu erzeugen ist trivial. Die Eingabe korrekt zu normalisieren entscheidet darüber, ob der Upload überhaupt jemanden trifft – und diesen Schritt kann ein Add-on für dich übernehmen, je Eingabetyp, auf jeder Zeile gleich.
Hash Data teilt die Aufgabe entsprechend auf:
| Funktion | Was sie tut |
|---|---|
=HASHEMAIL(email, [algorithmus]) | Entfernt Leerzeichen, schreibt klein, hasht dann |
=HASHPHONE(telefon, [algorithmus]) | Bringt die Nummer ins E.164-Format und hasht sie – ein Schritt, statt REGEXREPLACE in eine Digest-Formel zu verketten |
=HASH(wert, [algorithmus]) | Hasht den Wert exakt wie übergeben – keine Normalisierung, Groß- und Kleinschreibung zählt |
Vier Dinge, die dir das gegenüber einem selbst geschriebenen Skript bringt:
- Die Normalisierung steckt in der Funktion, nicht in einer Hilfsspalte, die du in jeder neuen Tabelle neu aufbauen musst.
- Keine 30-Sekunden-Grenze für benutzerdefinierte Funktionen, um die herum du konstruieren musst – warum das bei einer echten Liste zählt, steht in Weg 2.
- Deine Liste bleibt in der Tabelle. Nichts wird in eine fremde Website eingefügt.
- SHA3-256 ist verfügbar, was
computeDigest()in Apps Script selbst nicht anbietet.
Ein Vorbehalt, klar gesagt, weil er über die Funktionswahl entscheidet. =HASHPHONE() normalisiert auf E.164 – Ziffern mit führendem +. Das entspricht dem, was Google Ads dokumentiert. Metas dokumentiertes Beispiel geht in die andere Richtung: nur Ziffern, kein +. Für einen Meta-Upload normalisierst du die Nummer also selbst mit =REGEXREPLACE(A2, "[^0-9]", "") und hasht diese Zeichenfolge mit =HASH(). Eine Funktion bedient nicht beide Plattformen, weil die Plattformen sich nicht einig sind – denselben Punkt macht die Vergleichstabelle weiter unten.
Der kostenlose Tarif umfasst 100 Hash-Aufrufe pro Tag, der kostenpflichtige hebt die Grenze auf.
→ Hash Data im Google Workspace Marketplace installieren
Weg 2: die benutzerdefinierte Funktion selbst schreiben
Wenn du den Code lieber selbst besitzt, ist das hier alles. Öffne Erweiterungen → Apps Script, füge das ein, speichere und nutze =SHA256(A2) in der Tabelle.
/**
* Gibt den SHA-256-Digest der Eingabe als Hex in Kleinbuchstaben zurueck.
* Nimmt eine einzelne Zelle oder einen Bereich entgegen.
* @customfunction
*/
function SHA256(input) {
if (Array.isArray(input)) {
return input.map(function (row) {
return row.map(function (cell) { return SHA256(cell); });
});
}
if (input === '' || input === null || input === undefined) return '';
var bytes = Utilities.computeDigest(
Utilities.DigestAlgorithm.SHA_256,
String(input),
Utilities.Charset.UTF_8
);
return bytes
.map(function (b) { return ((b < 0 ? b + 256 : b)).toString(16).padStart(2, '0'); })
.join('');
}
Zwei Dinge bringen hier viele zu Fall, und beide lohnen sich zu verstehen, selbst wenn du das Skript nie selbst schreibst.
computeDigest() liefert ein vorzeichenbehaftetes Byte-Array zurück, keine Hex-Zeichenfolge. Apps Script gibt Bytes im Java-Stil mit Vorzeichen zurück, alles oberhalb von 0x7F kommt also negativ an. Genau das repariert b < 0 ? b + 256 : b. Lässt du es weg, bekommst du einen Digest voller --Zeichen, den keine Plattform akzeptiert. Lässt du padStart(2, '0') weg, verlierst du still führende Nullen einzelner Bytes und erzeugst einen Digest mit weniger als 64 Zeichen, der auf sehr schwer erkennbare Weise falsch ist.
Eine benutzerdefinierte Funktion muss innerhalb von 30 Sekunden zurückkehren, sonst zeigt die Zelle #ERROR!. Eine Variante pro Zelle – eine Formel in jeder Zeile – bricht bei einer echten Kundenliste zusammen. Deshalb prüft die Funktion oben zuerst auf ein Array: So geschrieben, kannst du =SHA256(A2:A5000) in eine einzige Zelle setzen und dir die ganze Spalte als ein Array zurückgeben lassen.
Weg 3: ein Web-Hasher
Über diesen Weg solltest du am gründlichsten nachdenken, denn er ist der naheliegendste und der einzige mit einem Offenlegungsproblem.
Eine Kundenliste in eine Website einzufügen ist eine Übermittlung personenbezogener Daten an denjenigen, der diese Website betreibt. Der Seite ist in der Regel nicht anzusehen, ob das Hashen in deinem Browser oder auf ihrem Server passiert – und die Antwort ist von erheblicher Bedeutung. Für eine einzelne Testzeichenfolge in Ordnung; weiter unten auf dieser Seite steht eine, die du dafür verwenden solltest. Für eine Liste echter Kunden: nein.
Weg 4: gar nicht hashen
Die vergessene Möglichkeit. Google Ads akzeptiert Kundendaten im Klartext und hasht sie vor dem Upload, und TikTok dokumentiert, dass es "accepts both hashed and original values."
Wenn dein Grund fürs Hashen also eine Richtlinie oder ein Vertrag ist, ist Hashing die Antwort. Wenn du angenommen hast, es sei verpflichtend, ist es das häufig nicht – und Vorab-Hashen bedeutet, dass du die Normalisierung besitzt, samt jedem Fehler darin, statt der Plattform. Das ist es wert, gewusst zu werden, bevor du eine Pipeline darum herum baust.
Dann: normalisieren, und zwar je Plattform
Diesen Teil überspringen die meisten Leitfäden, und er ist der Grund, warum Match-Raten einbrechen.
Google Ads
Customer Match dokumentiert für gehashte Spalten: alles kleinschreiben, Leerzeichen entfernen, "Format phone numbers using the E.164 format" und – ausdrücklich – "Include the country code and '+' sign."
Google dokumentiert eine reine Gmail-Regel an zwei Stellen, und sie sind nicht identisch – das sollte man wissen, bevor man eine davon in eine Pipeline kopiert.
Die Seite zur Customer Match-Datendatei sagt nur: "Remove all periods (.) that precede the domain name in gmail.com and googlemail.com email addresses." Punkte, sonst nichts.
Die Customer Match-API-Seite geht weiter, aber unter einer Überschrift, die auf Enhanced Conversions eingegrenzt ist: Punkte aus dem Nutzernamen entfernen und das Pluszeichen samt allem, was danach kommt. Das durchgerechnete Beispiel dort lautet Jane.Doe+Shopping@googlemail.com → jane.doe+shopping@googlemail.com (kleingeschrieben) → janedoe@googlemail.com.
Die Plus-Suffix-Hälfte ist also für Enhanced Conversions dokumentiert, nicht für den Upload einer Kundenliste. Wenn du eine Zielgruppenliste baust, ist die Punkte-Regel diejenige, die Google für diese Aufgabe tatsächlich dokumentiert. Worin beide übereinstimmen: Das gilt ausschließlich für gmail.com und googlemail.com. Es auf jede Domain anzuwenden ist ein eigener Fehler – viele Mailsysteme behandeln jane.doe@ und janedoe@ als verschiedene Personen.
Meta
Meta dokumentiert etwas anderes. Für E-Mail: "Trim any leading and trailing spaces. Convert all characters to lowercase." Überhaupt keine Gmail-Punkte-Regel.
Für Telefon: "Remove symbols, letters, and any leading zeros," dazu "Always include the country code as part of your customers' phone numbers." Metas eigenes durchgerechnetes Beispiel lautet (650)555-1212 → 16505551212 – Ländervorwahl, nur Ziffern, kein Pluszeichen.
Dieselbe Telefonnummer ergibt also zwei verschiedene Hashes
| Google Ads | Meta | |
|---|---|---|
| Telefon, dokumentiert | E.164, "include the country code and '+' sign" | "Remove symbols… and any leading zeros"; Beispiel → 16505551212 |
Gmail-Punkte und +-Suffix | Punkte entfernt für gmail.com / googlemail.com; die +-Suffix-Regel ist für Enhanced Conversions dokumentiert | Nicht dokumentiert |
| Kodierung | "Use hex SHA256" | "HEX representations… using lowercase for A through F" |
Eine gehashte Spalte kann nicht beide Plattformen bedienen. Wenn du bisher eine wiederverwendet hast, ist das deine Match-Rate.
TikTok ist der Ausreißer
TikTok dokumentiert deutlich weniger: "MD5 and SHA256 encryption is supported. The content of the file before encryption needs to be in all uppercase or lowercase." Es ist keine E.164-Anforderung veröffentlicht, und es werden sowohl gehashte als auch originale Werte akzeptiert. Nimm nicht an, dass Googles Regeln dort gelten.
Die Formeln, in der Reihenfolge ihrer Anwendung
In einer Hilfsspalte normalisieren, die Hilfsspalte hashen, dann nur den Digest behalten.
| Schritt | Formel |
|---|---|
| E-Mail, beide Plattformen | =LOWER(TRIM(A2)) |
Geschütztes Leerzeichen entfernen, das TRIM() übersieht | =TRIM(SUBSTITUTE(A2, CHAR(160), " ")) |
Gmail-Punkte und +-Suffix, nur Google Ads – siehe den Geltungsvorbehalt oben (angewendet auf B2, die kleingeschriebene E-Mail) | =IF(REGEXMATCH(B2, "@(gmail|googlemail)\.com$"), SUBSTITUTE(REGEXREPLACE(REGEXEXTRACT(B2, "^[^@]+"), "\+.*$", ""), ".", "") & REGEXEXTRACT(B2, "@.*$"), B2) |
| Telefon, nur Ziffern (Meta) | =REGEXREPLACE(A2, "[^0-9]", "") |
| Telefon, E.164 (Google Ads) | ="+" & REGEXREPLACE(A2, "[^0-9]", ""), sobald du sicher bist, dass die Ländervorwahl vorhanden ist |
Die letzte Zeile trägt einen Vorbehalt, der laut ausgesprochen gehört: Einer nationalen Nummer ein + voranzustellen erzeugt keine gültige E.164-Nummer. Aus 07700 900461 wird +7700900461, was falsch ist und nicht matchen wird. Die Ländervorwahl muss tatsächlich da sein.
Die Fehlerbilder, in der Reihenfolge ihres Auftretens
- Deine Tabelle zerstört die Daten, bevor du hashst. Eine 16-stellige Zahl wird zur wissenschaftlichen Notation,
07700 900461verliert die führende Null,+44…wird als Formel gelesen. Formatiere die Spalte als Klartext, bevor irgendetwas darin landet – nachträgliches Reparieren ist Datenverlust, keine Formatierung. - Groß- und Kleinschreibung sowie Leerzeichen.
John@undjohn@sind verschiedene Digests. Ebensojohn@x.comundjohn@x.commit einem Leerzeichen am Ende aus einem CSV-Export. UndTRIM()entfernt kein geschütztes Leerzeichen – genau das, was ein Copy-and-paste von einer Webseite hinterlässt. - Den Anzeigewert hashen.
(650) 555-1212ist nicht16505551212. Ist die Zelle als Telefonnummer formatiert, sind das, was du siehst, und das, was du hashst, verschiedene Zeichenfolgen. - Doppeltes Hashen. Die Formel über eine Spalte laufen lassen, die bereits Hashes enthält. Einfache Prüfung: Ein SHA-256-Hex-Digest ist immer exakt 64 Zeichen aus
0-9a-f,=LEN(B2)=64fängt das ab – und Abschneidungen gleich mit. - Falsche Kodierung. Ein Base64-Digest ist ein gültiger Hash der richtigen Eingabe und wird trotzdem nicht matchen. Etliche verbreitete Copy-and-paste-Schnipsel nutzen standardmäßig MD5 und Base64.
Vor dem Upload prüfen
Meta veröffentlicht den erwarteten Digest für john_smith@gmail.com:
62a14e44f765419d10fea99367361a727c12365e2520f32218d505ed9aa0f62f
Hashe genau diese Zeichenfolge mit deiner Formel. Kommt nicht exakt dieser Wert zurück, repariere die Formel – nicht die Liste. Das kostet dreißig Sekunden und ist der einzige Test, der "mein Hashing ist kaputt" von "meine Liste ist schlecht" unterscheidet, was von außen sonst ununterscheidbar ist.
Ein ehrliches Wort zum Datenschutz
Hashing ist Pseudonymisierung, keine Anonymisierung. Die DSGVO klärt das in Erwägungsgrund 26: "Einer Pseudonymisierung unterzogene personenbezogene Daten, die durch Heranziehung zusätzlicher Informationen einer natürlichen Person zugeordnet werden könnten, sollten als Informationen über eine identifizierbare natürliche Person betrachtet werden." Die Leitlinien 01/2025 des Europäischen Datenschutzausschusses zur Pseudonymisierung bauen genau auf diesem Ausgangspunkt auf.
Ein ungesalzener Telefon-Hash lässt sich per Brute Force durchgehen – der Zahlenraum ist klein genug, um ihn vollständig auszuschöpfen. Und salzen kannst du ihn nicht, weil genau das den Abgleich der Plattform verhindert. Gehashte Kundendaten sind weiterhin Kundendaten. Behandle sie so.
Wenn du fertig bist: gehashte Spalte kopieren, Inhalte einfügen als "Nur Werte", Rohspalte löschen.
Das Ganze, der Reihe nach
Welchen Weg du auch gewählt hast, die Abfolge ist dieselbe:
- Spalte als Klartext formatieren, bevor die Daten darin landen.
- In einer Hilfsspalte normalisieren, nach den Regeln der Plattform, zu der du hochlädst – nicht der anderen.
- Hilfsspalte hashen, Hex-SHA-256, sofern die Plattform nichts anderes sagt.
- Eine bekannte Zeichenfolge testen gegen Metas veröffentlichten Digest, bevor du der Spalte traust.
=LEN(B2)=64prüfen über den gesamten Bereich, um Abschneidungen und doppeltes Hashen zu finden.- Inhalte einfügen als "Nur Werte", Rohspalte löschen und hochladen.
Die Schritte 2 und 3 sind die, die Hash Data zu einer einzigen Funktion zusammenfasst – =HASHEMAIL() für E-Mail, =HASHPHONE() für Telefonnummern im E.164-Format, =HASH() für alles, was du selbst normalisiert hast. Unterstützt werden SHA256, MD5, SHA1, SHA512 und SHA3-256, und alles läuft innerhalb deiner Tabelle. Der kostenlose Tarif umfasst 100 Hash-Aufrufe pro Tag, der kostenpflichtige hebt die Grenze auf.
Quellen
- Google Tabellen Funktionsliste
- Apps Script – Utilities.computeDigest und DigestAlgorithm
- Apps Script – Benutzerdefinierte Funktionen in Google Tabellen
- Google Ads-Hilfe – Kundendatendatei formatieren
- Google Ads API – Get started with Customer Match
- Meta – Conversions API customer information parameters
- Meta – Custom Audiences guide
- TikTok – Guidelines for customer files
- DSGVO Erwägungsgrund 26 – Nicht anwendbar auf anonyme Daten
- EDSA-Leitlinien 01/2025 zur Pseudonymisierung
Plattformspezifikationen geprüft am 20. August 2026. Werbeplattformen überarbeiten diese Seiten; prüfe die Quelle vor einem großen Upload.