How do you install a visitor ID tag on a server-rendered site?
On a server-rendered site the tag goes in the one base template every page extends: the Rails application layout, Django's base.html, a Blade layout, _Layout.cshtml. Paste the vendor's <script> tag there as plain markup. A third-party tag with a remote src is not one of your own assets, so it does not need the asset pipeline, collectstatic or a bundler.
Two things go wrong on these stacks. First, a Content Security Policy that does not list the vendor's hosts blocks the tag without any error on the page. Rails, Django 6.0+, Laravel and Magento each have their own CSP settings. Second, newer tooling swaps pages without a full load: Turbo in Rails, wire:navigate in Livewire, enhanced navigation in Blazor. There the tag behaves like one in a single-page app, and it needs the hook named in its section below.
Where the tag goes and what to watch on each stack
| Stack | Where the tag goes | Swaps pages without a reload? | Built-in CSP to update |
|---|---|---|---|
| Ruby on Rails | app/views/layouts/application.html.erb | Yes, if Turbo Drive is on | config/initializers/content_security_policy.rb |
| Django | Your base template (for example base.html) | No | Django 6.0+: SECURE_CSP setting |
| Laravel | Your Blade layout | Only with Livewire wire:navigate | None built in; Vite nonce helper for your own assets |
| ASP.NET Core | Views/Shared/_Layout.cshtml or the Blazor App.razor | Yes in Blazor Web Apps (enhanced navigation) | None built in; set the header in middleware |
| Drupal | A theme library, or a contributed module | No | Depends on your modules |
| Magento / Adobe Commerce | Admin: HTML Head, Scripts and Style Sheets | No | Yes: restrict mode on payment pages (2.4.7+) |
| Eleventy | Your base layout in _includes | No | None; set it on your host |
| Plain HTML | Each page's <head> | No | None; set it on your host |
Which CSP entries does the tag need?
Two directives, both with the vendor's hosts. script-src lets the script load. connect-src lets it report, because it covers fetch(), XMLHttpRequest and navigator.sendBeacon(). Ask the vendor for both host lists. If the vendor's snippet includes an inline <script> block that loads the tag, that inline block also needs your nonce or a hash. Test in report-only mode first when your framework offers it, and read the console for violations before you enforce.
How do you add the tag on Ruby on Rails?
Where it goes: Paste the vendor's <script> tag into app/views/layouts/application.html.erb, inside <head>. It is external markup, so the asset pipeline does not touch it; fingerprinting and bundling apply only to your own JavaScript files.
What breaks it on Ruby on Rails
- If the app uses Turbo Drive, it follows links "without doing a full reload". A script in
<head>runs on the first page only. Record later pages in aturbo:loadlistener, which fires once after the first page load and again after every Turbo visit. - If the app has a CSP in
config/initializers/content_security_policy.rb, add the vendor's hosts topolicy.script_srcandpolicy.connect_src. If the vendor snippet has an inline block, wrap it withjavascript_tag nonce: trueso Rails applies the nonce.
How to check it on Ruby on Rails
Open the site, then click an internal link. With Turbo on, the Network panel shows a fetch rather than a new document. Check that the vendor records the second page.
Sources: Turbo Handbook: Drive (read 2026-09-25); Turbo Reference: Events (read 2026-09-25); Rails Guides: Security (Content Security Policy) (read 2026-09-25); Rails Guides: Asset pipeline (read 2026-09-25).
How do you add the tag on Django?
Where it goes: Paste the tag into the base template your other templates {% extends %}, inside <head>. Django's static files system ({% static %}, collectstatic) is for files you host yourself; a vendor URL needs neither.
What breaks it on Django
- Django 6.0 added built-in CSP:
ContentSecurityPolicyMiddlewareplus theSECURE_CSPorSECURE_CSP_REPORT_ONLYsettings. It is off until you configure it. If you use it, add the vendor's hosts to thescript-srcandconnect-srclists, and give any inline vendor blocknonce="{{ csp_nonce }}"(this needs thecspcontext processor). - On Django before 6.0, CSP came from a third-party package or your web server, so check there instead.
How to check it on Django
Load two pages and confirm the vendor records both. If you use SECURE_CSP_REPORT_ONLY, check the console for violation reports that name the vendor's hosts before you switch to enforcing.
Sources: Django 6.0: How to use CSP (read 2026-09-25); Django 6.0 release notes (read 2026-09-25); Django: Managing static files (read 2026-09-25).
How do you add the tag on Laravel?
Where it goes: Paste the tag into the Blade layout your pages extend, inside <head>. If you prefer to push it from a view with @push('scripts'), the layout must render @stack('scripts'); without the matching stack the pushed tag is silently dropped.
What breaks it on Laravel
- Laravel sets no CSP of its own.
Vite::useCspNonce()in a middleware adds a nonce to Laravel's own Vite-built tags. Add the vendor's hosts to the same header'sscript-srcandconnect-src. - Livewire's
wire:navigatefetches the next page in the background and swaps it in instead of a full page visit. On those links the tag behaves like one in a single-page app, so record later pages from Livewire's navigation event as your Livewire version documents it.
How to check it on Laravel
View source to confirm the tag renders once. If you use wire:navigate, click a navigate link and check that the vendor records the new page.
Sources: Laravel: Blade stacks (read 2026-09-25); Laravel: Vite (CSP nonce) (read 2026-09-25); Livewire: wire:navigate (read 2026-09-25).
How do you add the tag on ASP.NET Core?
Where it goes: For MVC and Razor Pages, paste the tag into Views/Shared/_Layout.cshtml. Use @section Scripts { } only when the tag belongs on some pages and not others. The layout renders that section with RenderSection("Scripts", required: false).
What breaks it on ASP.NET Core
- In a Blazor Web App (.NET 8 and later), enhanced navigation is on by default and loads internal pages without a full reload. Microsoft's docs warn that page-specific JavaScript "may not be executed again as expected" after an enhanced navigation, and recommend an event listener instead. Record later pages from
Blazor.addEventListener('enhancedload', ...), which fires each time the page updates. - ASP.NET Core sends no CSP by default. If yours is set in middleware or on the server, add the vendor's hosts to
script-srcandconnect-src.
How to check it on ASP.NET Core
In a Blazor app, click an internal link and confirm there is no new document request, then check that the vendor still records the page.
Sources: Microsoft Learn: Layout in ASP.NET Core (read 2026-09-25); Microsoft Learn: Blazor navigation (read 2026-09-25); Microsoft Learn: Blazor JavaScript with static SSR (enhancedload) (read 2026-09-25).
How do you add the tag on Drupal?
Where it goes: Drupal core has no admin field for head scripts. Either declare the tag as an external library in your theme's *.libraries.yml (type: external) and attach it globally, or use a contributed module built for this, such as Header and Footer Scripts.
What breaks it on Drupal
- Drupal's own docs say loading libraries from a CDN is "in general not a good idea". A vendor tag is an exception you cannot avoid, so keep it in one place and write down which module or theme holds it. A library defined in a theme stops loading if you switch themes.
- Library changes do not show until the cache is rebuilt (
drush cr).
How to check it on Drupal
Rebuild the cache, then view source on two different page types (a node and a view) to confirm the tag is on both.
Sources: Drupal: Adding assets via libraries.yml (read 2026-09-25); Drupal.org: Header and Footer Scripts module (read 2026-09-25).
How do you add the tag on Magento?
Where it goes: In the Admin: Content > Design > Configuration, edit the store view, then Other Settings > HTML Head > Scripts and Style Sheets. Adobe describes this field as the place for third-party JavaScript that must load before the <body> tag.
What breaks it on Magento
- Adobe's own help page warns that JavaScript in this field "must be whitelisted in the Content Security Policy (CSP) settings, otherwise it will not be executed on the Checkout pages". From 2.4.7, CSP runs in restrict mode on payment pages and report-only mode elsewhere. So a tag can work on every catalog page and still be blocked at checkout. Allow the vendor's hosts, or the hashes of any inline vendor block, in a module's
csp_whitelist.xml, then flush the cache.
How to check it on Magento
Check a category page and then a checkout page separately. On checkout, look for CSP violation messages in the console; a clean catalog page proves nothing about checkout.
Sources: Adobe Commerce: Page setup (HTML Head) (read 2026-09-25); Adobe Commerce: Content security policy overview (read 2026-09-25); Adobe Commerce PHP Developer Guide: Content Security Policies (read 2026-09-25).
How do you add the tag on Eleventy?
Where it goes: Paste the tag into the base layout your pages use (for example _includes/base.njk). You do not need a custom tag or shortcode for one fixed script. Those help only if the tag needs values, such as a different ID per environment.
What breaks it on Eleventy
- A page with its own layout, or none, will not get the tag. Check that every template in the site chains up to the base layout.
How to check it on Eleventy
After a build, list any page missing the tag with grep -rL --include='*.html' vendor-host _site (use your vendor's host and output folder).
Source: Eleventy: Layouts (read 2026-09-25).
How do you add the tag on plain HTML?
Where it goes: Paste the tag into the <head> of every page. Keep the async or defer attribute the vendor supplied: both only work on a script with a src, and they stop the download from blocking HTML parsing.
What breaks it on plain HTML
- With no shared template, the usual failure is a page that never got the tag. It is often a landing page someone added later.
How to check it on plain HTML
Search the site's files for the vendor's host and compare that list with the list of pages.
Source: MDN: The script element (read 2026-09-25).
Where to go next
- Post-launch QA test script: what to check after the tag fires, before sales sees a signal
- Exclude employees and bad-fit traffic: the next source of noise once the install is correct
- JavaScript apps: if part of the site is a single-page app