Google Analytics (GA4)
Google Analytics 4 wiring through Piko's built-in analytics frontend module, gtag.js loaded via WithFrontendModule(piko.ModuleAnalytics, ...), with automatic SPA page-view tracking.
Overview
Unlike server-side analytics collectors, GA4 is a frontend module. The analytics module bundles the loader for gtag.js and pushes a page-view event on every client-side route change, keeping the GA4 dashboard accurate for SPAs. The module ships with the core piko.sh/piko package, so no separate go get step. Register it through WithFrontendModule(piko.ModuleAnalytics, piko.AnalyticsConfig{...}) to turn it on. The frontend module is the registration. There is no separate WithAnalyticsProvider step.
Enabling the module wires GA4 into Piko's client-side hook bus. Page views, SPA navigation timing, server-action outcomes, modal opens, and JavaScript errors all flow to GA4 as page_view, navigation, server_action, modal_view, and exception events with no extra code. An analytics:track hook sends custom events. A page can also embed a <script id="pk-page-data"> JSON block. The module re-reads it on each navigation and merges its metadata into every GA4 event.
AnalyticsConfig.TrackingIDs accepts more than one GA4 measurement ID. One slice fans out to every property, each configured with its own gtag('config', ...) call (for example one per environment, or shadow tracking during a migration). AnonymiseIP sets anonymize_ip on the gtag config and delegates IP handling to Google for GDPR-aware deployments. DebugMode sets debug_mode on the gtag config, which routes events into the GA4 DebugView, and also logs each dispatched event to the browser console. DisablePageView opts out of automatic tracking when you want to call gtag() yourself.
AnalyticsConfig is one struct shared with the Google Tag Manager path. Setting GTMContainerID loads a GTM container from the same module. GA4-only setups leave it empty.
The analytics bundle loads with a computed SRI integrity hash and a crossorigin attribute, so adding GA4 does not weaken the script integrity of the page.
GA4 talks to *.google-analytics.com and loads its tag from www.googletagmanager.com, so you need CSP entries for both. Piko's default CSP omits them. Add them through WithCSP as shown below.
Configuration
AnalyticsConfig holds the wiring. GA4-only setups need only TrackingIDs.
import (
"piko.sh/piko"
)
ssr := piko.New(
piko.WithFrontendModule(piko.ModuleAnalytics, piko.AnalyticsConfig{
TrackingIDs: []string{"G-XXXXXXXXXX"}, // required; one or more GA4 measurement IDs
AnonymiseIP: true, // optional; set anonymize_ip on the gtag config
DebugMode: false, // optional; route events to GA4 DebugView and log to the console
DisablePageView: false, // optional; opt out of automatic SPA page-view tracking
}),
)
Content Security Policy
GA4 works alongside Piko's default CSP. Extend it with the Google domains. WithPikoDefaults already allows HTTPS images, so the measurement pixel needs no extra img-src entry:
piko.WithCSP(func(b *piko.CSPBuilder) {
b.WithPikoDefaults().
ScriptSrc(
piko.CSPSelf,
piko.CSPHost("https://www.googletagmanager.com"),
).
ConnectSrc(
piko.CSPSelf,
piko.CSPHost("https://www.google-analytics.com"),
piko.CSPHost("https://*.google-analytics.com"),
piko.CSPHost("https://*.analytics.google.com"),
piko.CSPHost("https://*.googletagmanager.com"),
)
}),
See also
Other analytics integrations:
- Google Tag Manager, same frontend module, GTM container loading instead of direct gtag.
- Plausible Analytics, privacy-first server-side collector via
WithBackendAnalytics.
Framework docs:
- Analytics API reference, every type and method on the analytics service.
- Frontend modules reference, every module enabled through
WithFrontendModule. - How to configure CSP, extending the default CSP with third-party domains.
External:
- GA4 documentation, authoritative reference for tag and event semantics.
- GA4 measurement ID, finding the
G-XXXXXXXXXXvalue for your property.