Thema: Content Security Policy (CSP), Google Tag Manager (GTM), Nonce-Variable, Custom JS Variable
Wahrscheinlich bist du auf diesen Artikel gestossen, weil dein Tracking plötzlich nicht mehr funktioniert – und du in der Console eine kryptische Fehlermeldung entdeckt hast, die besagt, dass die Content Security Policy (CSP) die Ausführung deines Trackings verhindert hat:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' https://trusted.cdn.com". Either the 'unsafe-inline' keyword, a hash ('sha256-abc123...'), or a nonce ('nonce-...') is required to enable inline execution.
Nach Anleitungen, wie man genau dieses Problem mit dem Google Tag Manager löst, sucht man oft vergeblich – oder findet an Entwickler gerichtete Tutorials die für deinen Fall wenig hilfreich sind. Been there, done that. Und genau deshalb zeige ich dir hier, wie du Schritt für Schritt das Problem identifizierst und löst – ganz ohne IT-Studium.
So findest du das CSP-Problem, das deinen Tag Manager blockiert
Die Fehlermeldung, die du wahrscheinlich bereits entdeckt hast – falls nicht, klicke F12 oder Strg + Umschalt + C – gibt dir bereits den ersten Hinweis, welches Script zu Problemen führt. Am linken Rand sollte dir angezeigt werden, welche Datei gegen die CSP verstossen hat.

Die Konsole sagt dir, welche Datei und welche Zeile in der Datei, Probleme macht
Du kannst zusätzlich im Tab „Network“ überprüfen, welche Requests durch die CSP geblockt wurden. In der Spalte Status steht bei den entsprechenden Anfragen jeweils (blocked:csp), sowie zusätzliche Informationen, die du dir notieren solltest (Domain, Type), da sie den Entwicklern helfen, die CSP korrekt für eure Seite einzustellen. Mehr dazu erzähle ich aber speziell im Artikel zu Subresource Loading und Drittanbieter-Skripten.[Coming soon]
Besonders auschlussreich ist es, im Network-Tab zu überprüfen, ob die Datei gtm.js?id=GTM-[XXXXXXXX] geblockt wurde. Das ist dein Google Tag Manager Container. Falls nein solltest du überprüfen, ob das Inline-Script geladen wurde:
- weil eure CSP 'unsafe-inline' erlaubt: Das ist nicht empfohlen.
- weil du im Script-Tag des GTM einen „hash“ siehst: In diesem Fall solltest du deiner IT-Abteilung mitteilen, dass extern darin geladene Scripts regelmässig upgedated und verändert werden und das Problem nicht per Hash gelöst werden kann.
- weil du im Script-Tag des GTM einen „nonce“ siehst: In diesem Fall hast du bereits alle Voraussetzungen erfüllt, die du zur Lösung des CSP-Problem benötigst. Du kannst direkt zu "So nutzt du deinen Nonce im GTM" springen.
Info: Ein Nonce («number used once») ist ein einmaliger Token, der bei jedem Laden der Seite neu generiert wird und sozusagen als Einmal-Passwort für die Ausführung des Scripts dient Quasi ein Einmal-Passwort für die Ausführung des Scripts. Ein Hash wiederum ist eine Art «Prüfsumme» oder ein Fingerabdruck für dein Script und setzt voraus, dass dein Script sich nicht verändert und innerhalb des Skripts auf keine anderen Ressourcen (z.B. extern gehostete Scripts) zugegriffen wird.
GTM-Einbindung geht nicht ohne Nonce
Wie schon angedeutet, kannst du den Google Tag Manager nicht gemeinsam mit einer CSP nutzen, ohne auch einen Nonce zu generieren. Zumindest nicht, ohne die Sicherheitslücke von 'unsafe-inline' offen zu lassen und deine IT-Security zu kompromittieren. Falls dein Impuls jetzt ist das Script einfach extern oder einer Datei zu laden, muss ich dich enttäuschen: Das GTM-Snippet ist auf eine Inline-Implementation angewiesen, beispielsweise um den Data Layer erfolgreich zu initialisieren.
Allein deshalb wirst du nicht darum herumkommen, bei deiner IT-Abteilung anzufragen, ob sie «bei jedem Pageload einen Nonce generieren und in den DOM pushen können» und ob sie das GTM-Snippet im Head gleich um den Nonce ergänzen können:

Alternative: Oder du stellst dein GTM-Set-Up komplett auf server-seitiges Tracking um. Da die Content-Security-Policy einschränkt, was im Browser geladen werden darf, umgeht server-side tagging dieses Problem vollständig.
So nutzt du deinen Nonce im GTM
Sobald dein GTM-Snippet den Nonce bekommen hat, kannst du ihn wieder nutzen. Allerdings wird dir die CSP immer noch alle externen Einbindungen (z.B. HotJar) und Custom HTML Tags blockieren. Zumindest zweiteres lässt sich mit der gleichen Methode lösen, wie das GTM-Snippet selbst. Aber da der Nonce bei jedem Page Load neu generiert wird, musst du diesen Wert dynamisch abgreifen und in deine Tags einfügen. Dies funktioniert am einfachsten über eine DOM-Element-Variable mit CSS-Selektor. Wie genau der Selektor lautet, kommt auf deine konkrete Seitenarchitektur an, aber es könnte in etwa so aussehen:

Sobald die Variable angelegt ist, kannst du in deinem Tag Assistant die Vorschau aktivieren und testen, ob der Wert richtig abgegriffen wird. Wenn das klappt, musst du nur mehr deine Custom HTML Tags ergänzen. Aus <script> muss <script nonce="{{nonce}}"> werden. Wichtig ist dabei, dass du {{nonce}} wirklich tippst, nicht einfach reinkopierst: Der GTM akzeptiert dynamisch Werte aus Variablen nur, wenn sie aus dem Dropdown-Menü ausgewählt wurden.

Du solltest das Kontextmenü sehen, sobald du {{ getippt hast
Hinweis: Das gilt nicht nur für Nonces. Wenn du Probleme hast, Variablen in einem Custom HTML Script zu verwenden, überprüfe ob die Variable aus dem Kontextmenü ausgewählt wurde, das beim Tippen erscheint. Bei Copy & Paste erkennt der Tag Manager nicht, dass es eine Variable ist, sondern interpretiert sie als normalen Text.
Custom Javascript Variablen & CSP
Vielleicht hast du schon bemerkt, dass ich eine Art übergangen habe, wie man eigenes JavaScript im Google Tag Manager benutzen kann: Custom Javascript Variablen, respektive Variablen vom Typ „Benutzerdefiniertes JavaScript“ in der deutschen Version (nicht zu verwechseln mit einer normalen Javascript-Variable – das ist noch einmal ein anderer Typ, der fast gleich heisst).
Falls dein Tracking-Setup auf Custom JS Variablen angewiesen ist, habe ich schlechte Nachrichten: Diese wirst du diese mit einer CSP ziemlich sicher nicht mehr nutzen können. Zumindest nicht, ohne dir ein massives Loch in deine IT-Security zu reissen. Eine Variable aus benutzerdefiniertem Javascript ist nämlich darauf angewiesen, dass 'unsafe eval' in der Content Security Policy erlaubt ist. Und das ist noch einmal ein Stückchen gefährlicher, als 'unsafe-inline' zu erlauben.
Stell es dir in etwa so vor: unsafe-inline ist in etwa, wie den Schlüssel in deinem unversperrten Auto stecken zu lassen. unsafe-eval hingegen ist, als ob du deinen Fahrzeugausweis und einen unterschriebenen Blanko-Kaufvertrag für das Auto auf dem Beifahrersitz liegen lässt, damit der Dieb das Auto einfach auf sich ummelden kann. Zwischen den beiden Regeln liegen sicherheitstechnisch Kilometer und unsafe-eval ermöglicht bösen Akteuren meist deutlich tiefer in dein System einzudringen und erschwert es extrem, den Schaden rückgängig zu machen.
Läuft dein Tracking wieder?
Sofern dein Problem hauptsächlich darin bestand, dass dein Google Tag Manager Container nach der Implementierung der CSP nicht mehr geladen hat oder deine selbstgeschriebenen Custom HTML Scripts nicht mehr funktioniert haben, solltest du damit deine Probleme bereits gelöst haben. Falls jetzt allerdings nur ein Teil deines Trackings wieder funktioniert und Social Media Pixel und andere Tools, die du als Teil eines Custom HTML Tags oder per Vorlage eingebunden hast, noch Schwierigkeiten machen, gibt es noch einen zusätzlichen Schritt, den du beachten musst: Was genau, erkläre ich dir hier. [Coming soon]
Alternativ darfst du dich natürlich auch gerne bei mir melden und wir sehen, ob wir gemeinsam dein Problem lösen können.