-
Notifications
You must be signed in to change notification settings - Fork 1
Analytics
🌐 This page in: English · Português
Analytics in eQuantic.UI is a capability, not a script you paste: a page asks for IAnalytics
the way it asks for a camera, and never learns who is listening. The eQuantic.UI.Gtm package is
an INSTALLER: one call wires a Google Tag Manager container to that capability, end to end.
Since 0.2.0-preview.29
using eQuantic.UI.Gtm;
builder.Services.AddUI(options => options
.ScanAssembly(typeof(Program).Assembly)
.UseGtm("GTM-XXXXXXX"));That one call installs three things into the HTML shell:
- The official container snippet: the same bytes Google documents, parameterized only where GTM itself templates them.
-
The installer declaration (
window.__EQ_ANALYTICS__): what arms the runtime'sIAnalyticsrealization. Without an installer, tracking is a silent no-op by design. -
SPA page views: the client router announces every committed navigation
(
eq:navigate), and the shell turns it intopage_viewpushes carryingpage_pathandpage_title, GA4's own field names. The container sees the initial load by itself; these are the navigations it cannot see.
The container id is validated at startup: a typo'd id installs a container that silently collects nothing, and that is discovered in next month's empty report, so refusing early is the kinder failure.
public override VisualNode Build(ComponentContext context)
{
_analytics = context.GetService<IAnalytics>();
// …
}
private async Task Submit()
{
// …after the server said yes:
_analytics?.Track("sign_up");
_analytics?.Track("purchase", new Dictionary<string, object?>
{
["value"] = 42,
["currency"] = "EUR",
});
}Track is fire-and-forget by contract, because analytics must never make a page wait. Event names are
YOUR vocabulary (sign_up, begin_checkout); the framework never invents or prefixes any. On the
server the same call is a no-op: SSR is not a user, and a page that tracked during rendering would
count its own crawlers.
A GTM container loads into the DOCUMENT and never unloads, so in a SPA a "per-page container"
cannot exist. Per-route variation is what the container's own triggers are for: the automatic
page_view carries page_path precisely so marketing can fire tags per route without the app
changing, which is the entire point of a tag manager.
What does exist is the agency-plus-client case: call UseGtm once per container. The second call
adds only its snippet; both ride the same dataLayer (GTM's own multi-container rule, enforced
at startup).
.UseGtm("GTM-XXXXXXX", gtm => gtm
.WithDataLayerName("eqData") // when another script already owns `dataLayer`
.WithoutSpaPageViews() // container uses GA4's history trigger instead
.WithEnvironment("auth…", "env-9")) // GTM environments (gtm_auth / gtm_preview)Turn WithoutSpaPageViews() on when the container tracks history changes itself, or the same
navigation counts twice.
-
The
<noscript>iframe from Google's install instructions. It measures users whose browsers run no JavaScript, and such a user gets no app at all here: there is nothing to measure. -
Consent Mode helpers. Consent is a product decision with legal weight; v1 does not wrap it.
A consent banner built with the SDK can push consent updates as ordinary dataLayer events
through
Trackin the meantime. -
A native realization.
IAnalyticsresolves to a no-op in a Photon window today; the mobile analytics bridges join with the native track.
-
Server Integration:
AddUI, the shell, and whereUseGtmhangs. -
Capabilities: the ask-by-interface pattern
IAnalyticsfollows.
🌐 English · Português
🏁 Start here
📱 Write-once
- Write-Once Components
- Declarative Surface
- Photon Engine
- Design System
- Capabilities
- Storage
- Forms
- Code Editor
- Markdown
- Mermaid
- Email Rendering
🏗️ Architecture
⚙️ Compilation
- Compiler
- Compile-Time Evaluation
- Supported C# Features
- External Type Resolution
- Build Flow
- Diagnostics
⚡ Runtime
🔌 Server
🎨 Ecosystem
🚀 Development