Google Tag Manager mit Content-Security-Policy nutzen

GTM mit CSP einsetzen? Gar nicht so einfach. Warum das so ist, wie es trotzdem klappt und wie du die grössten Fallstricke vermeidest, erfährst du hier.

Veröffentlicht: 09.06.2025 | Aktualisiert: 16.06.2026
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.

CSP Errors von meiner Seite mit Hervorhebung

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.

Besonders aufschlussreich 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:

Info: Ein Nonce (« number used once ») ist ein einmaliger Token, der bei jedem Laden der Seite neu generiert wird – quasi ein Einmal-Passwort für die Ausführung des Scripts. Ein Hash wiederum ist eine Art « Prüfsumme » oder Fingerabdruck für dein Script und setzt voraus, dass sich dein Script nicht verändert und innerhalb des Skripts auf keine anderen Ressourcen (z.B. extern gehostete Scripts) zugegriffen wird.


GTM-Einbindung geht nur mit unsafe-inline oder Nonce

Vorneweg: Für sehr einfache, rein statische Webseiten ohne Logins oder Formulare kann eine strenge CSP Overkill sein. In solchen Fällen ist das Risiko einer Inline-Sicherheitslücke geringer – und manche Betreiber entscheiden sich bewusst dafür, unsafe-inline zuzulassen, weil es für ihr Szenario ausreichend sicher ist. Meine Webseite fällt beispielsweise genau in diese Kategorie. Wenn das auf deine Webseite ebenfalls zutrifft, kann es sich lohnen, gemeinsam mit der IT-Abteilung zu prüfen, ob die CSP notwendig ist und ob die Downstream-Effekte für euer Web-Tracking bedacht wurden und in die Risikoabwägung eingeflossen sind. Falls ja, wirst du aber wahrscheinlich nicht um ein bisschen Zusatzaufwand herumkommen.

Wie schon angedeutet, kannst du den Google Tag Manager meistens 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 die Schutzwirkung der CSP deutlich zu schwächen. Falls dein Impuls jetzt ist, das Script einfach extern in 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:

Head meiner Seite mit Nonces

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, da die Tracking-Skripte nicht im Browser laden.


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:

Eine Nonce-Variable im GTM

Sobald die Variable angelegt ist, kannst du im 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 dynamische Werte aus Variablen nur, wenn sie aus dem Dropdown-Menü ausgewählt wurden. Unter Umständen musst du ausserdem bei document.write den Haken setzen, bevor deine Custom HTML Tags wieder funktionieren.

Eine Nonce-Variable im GTM

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 mit einer CSP ziemlich sicher nicht mehr nutzen können. Zumindest nicht, ohne dir ein kleines 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.

Alternativ darfst du dich natürlich auch gerne bei mir melden und wir sehen, ob wir gemeinsam dein Problem lösen können.

Lass dich zurückrufen

Hinterlasse kurz deine Nummer: Ich melde mich in der Regel innerhalb von 24 Stunden persönlich bei dir.

Bitte gib deinen Namen ein.
Bitte gib dein Unternehmen ein.
Bitte gib eine gültige Schweizer Telefonnummer ein.

Danke, deine Rückrufanfrage ist angekommen

Ich melde mich in der Regel innerhalb 24 Stunden bei dir.

Falls ich dich nicht erreiche, versuche ich es ein zweites Mal oder hinterlasse eine Nachricht um einen Termin abzumachen.

Oder lieber per E-Mail?

Ich antworte dir meistens innerhalb der nächsten paar Stunden. Wenn du möchtest, kannst du bereits erklären, um was es geht, und mir einen Link zu deiner Webseite hinterlassen.