Google Tag Manager - v1.0.0
Snippet Installer
The snippet installer emits the standard Google Tag Manager <script> head snippet and <noscript> body fallback for a configured container ID. It's completely standalone — no OAuth, no base-package requirement — and safe to include unconditionally in shared layouts.
Blade directives
Set your container ID (see Environment variables) and drop the directives into your layout.
@gtmSnippet
Emits both the head <script> block and the body <noscript> fallback in one call. Simplest, but slightly less optimal than splitting the two blocks.
<!DOCTYPE html>
<html>
<head>
@gtmSnippet
</head>
@gtmSnippetHead and @gtmSnippetBody
Splits the head and body blocks — Google's recommended placement for higher tag fidelity.
<!DOCTYPE html>
<html>
<head>
@gtmSnippetHead
{{-- other head content --}}
</head>
<body>
@gtmSnippetBody
{{-- page content --}}
</body>
</html>
Safe to include unconditionally
When the snippet is disabled or the container ID is missing, all three directives render an empty string — not a broken <script> tag or a <!-- disabled --> marker. That means:
- You do not need
@if( config('google-tag-manager.snippet.enabled') )wrappers. - Local development without
GTM_CONTAINER_IDset is silent — no console warnings. - Feature flags that toggle
snippet.enabledat runtime take effect on the next request.
React component
For SPAs, mount <GtmSnippet /> once high in the tree:
import { GtmSnippet } from '@/js/vendor/google-tag-manager/react'
export function App() {
return (
<>
<GtmSnippet containerId="GTM-XXXXXXX" />
{/* ... */}
</>
)
}
Props:
| Prop | Type | Default | Purpose |
|---|---|---|---|
containerId |
string | — | Required. The GTM container ID. |
dataLayerName |
string | 'dataLayer' |
The dataLayer variable name. Only override when your app already uses a custom name. |
Multiple mounts with the same containerId are safe — the installer keys the injected script by container ID and no-ops on duplicate calls.
The React component does not render the <noscript> body fallback. Server-render that block via @gtmSnippetBody, or add your own <noscript> where you mount the SPA.
Vue component
<script setup>
import { GtmSnippet } from '@/js/vendor/google-tag-manager/vue'
</script>
<template>
<GtmSnippet container-id="GTM-XXXXXXX" />
<!-- ... -->
</template>
Props mirror the React component:
| Prop | Type | Default |
|---|---|---|
containerId |
string | — (required) |
dataLayerName |
string | 'dataLayer' |
Same caveat about <noscript> — Vue-side is client-only.
How the container ID gets to the client
The Blade directives resolve google-tag-manager.snippet.container_id server-side and emit it inline in the <script> tag — no extra config or JS bridge needed.
For React and Vue, you pass the container ID as a prop. If your admin panel manages the container ID dynamically, expose it via your app's data layer or an API endpoint and thread it into the component prop.
Security notes
- Container ID escaping. The Blade directive escapes the container ID for both the JavaScript string interpolation and the
<noscript>srcattribute. An injection payload in the container ID (e.g.GTM-X'); alert(1);//) will not break out of the JS string or the HTML attribute. - CSP. The GTM
<script>block loadshttps://www.googletagmanager.com/gtm.js. If you use Content-Security-Policy, addhttps://www.googletagmanager.comtoscript-srcand (for the noscript iframe)frame-src. - Consent Mode. The snippet does not implement Google Consent Mode. Handle consent in the container itself via GTM's built-in consent settings, or in your host app before rendering the snippet.
Related
- Components — the admin-side Livewire, React, and Vue components (not the snippet)
- Configuration — every knob on the
snippet.*config