Feedback & status

AppAnalyticsHead

One include for a Razor page's <head> that wires up @webority/analytics.

<app-analytics-head gtm-id="GTM-XXXX" clarity-id="abcd1234" />

<app-analytics-head> is Razor-only, with no React counterpart: a React portal calls initConsent/loadTags/captureAttribution from @webority/analytics in its own bootstrap instead. This tag does the server-rendered equivalent in one line: it serves the @webority/analytics browser bundle, initializes consent (deciding opt-in from Cloudflare's CF-IPCountry header unless you force it), loads Tag Manager / Clarity / Ahrefs from the ids you pass, captures marketing attribution, and keeps <app-consent-banner> in sync: opening it for a visitor who has not decided yet and re-syncing its switches whenever consent is saved.

It belongs in <head>, once, on every page. This sandbox's own layout carries one with no ids: that is what makes the AppConsentBanner doc page's demo open for you on first visit. gtm-id / clarity-id / ahrefs-key come from the product's own marketing config (marketing.json via apply-tokens), not this component. GA4 is never loaded here: it runs inside the Tag Manager container, since loading it a second time double counts page views.

Playground

Every attribute, shown as the markup it produces. This page cannot render the include live, because a second copy would re-initialize the consent record this layout already set up, so try the real thing on the AppConsentBanner page instead.

<app-analytics-head gtm-id="GTM-XXXX" />

In your layout's <head>

Once, above everything else that needs consent to have already run.

Full setup
The ids come from your product's marketing config, never hardcoded.
Show code
<head>
  <app-analytics-head gtm-id="@Configuration["Seo:GtmContainerId"]"
                       clarity-id="@Configuration["Seo:ClarityProjectId"]"
                       ahrefs-key="@Configuration["Ahrefs:AnalyticsKey"]"
                       cookie-domain=".example.com" />
</head>

<app-consent-banner policy-href="/cookie-policy" />
<a href="#" data-consent-settings>Cookie settings</a>
Ask every visitor first
For a site whose policy promises consent first in every country. Consent Mode starts denied everywhere, Tag Manager and Ahrefs load only after the visitor consents, Accept grants analytics but no Google ad signals, and the choice lasts six months.
Show code
<app-analytics-head gtm-id="@Configuration["Seo:GtmContainerId"]"
                     ahrefs-key="@Configuration["Ahrefs:AnalyticsKey"]"
                     strict-opt-in="true"
                     consent-days="182" />

When to use

Use it when

  • Any Razor page or layout that needs consent, tags, and attribution wired up in one line.
  • You already have <app-consent-banner> on the page (or in the layout) and want it to open and re-sync automatically.

Reach for something else when

  • You're on the React surface. → initConsent / loadTags / captureAttribution from @webority/analytics, at your app's bootstrap

Attributes

AttributeTypeDefaultDescription
gtm-idstring-Google Tag Manager container id.
clarity-idstring-Microsoft Clarity project id.
ahrefs-keystring-Ahrefs Web Analytics key.
cookie-domainstring-Cookie domain the consent record spans (e.g. website + portal subdomains).
requires-opt-inbool?-Force the opt-in consent default on or off. Omit to decide from the visitor's country (the CF-IPCountry header): the EEA, the UK and Switzerland opt in, everywhere else defaults to granted, and a missing/unrecognised country opts in.
strict-opt-inboolfalseAsk every visitor first, in every region: Consent Mode starts denied everywhere, and Tag Manager and Ahrefs load only after consent. Cannot be combined with requires-opt-in="false".
ad-storagebool?-Whether marketing consent also grants Google's ad signals. Omit for the default: on, or off under strict-opt-in.
consent-daysint?365How many days the visitor's choice lasts.