01
Start from default denied
The page initializes consent state before it loads analytics. Until the visitor opts in, analytics storage remains denied and the GTM container is not invited to make the decision on its own.
The banner explains the purpose in plain language, offers equivalent accept and reject actions and exposes cookie settings again in the footer. Refusal is a supported product state, not an error path.
02
One measurement layer
GA4 is configured inside GTM rather than installed as a second independent page script. The application pushes named events into one data layer for booking clicks, form progress and successful submissions.
This keeps event naming, consent behaviour and environment checks in one place. It also reduces the chance that two implementations count the same page view.
03
Test the states, not only the tags
The QA matrix includes a first visit, acceptance, rejection, reopening preferences and withdrawing a prior choice. The network panel is checked before and after consent, and functional actions must work in every state.
GTM Preview and GA4 DebugView validate the measurement path. Browser storage and request inspection validate the privacy claim. Both are needed.
04
Keep ownership visible
The legal page lists the operator, purpose, lawful basis, retention context and third-party processor. Event names live in the codebase, while marketing configuration lives in the GTM workspace.
That boundary lets the site evolve without hiding what data is collected or who can change the measurement logic.