Google Tag Manager
GTM is a way to ship analytics + pixel tracking on your public forms without writing code. You connect your GTM container once; from then on, the public form auto-injects the GTM snippet and pushes events to the dataLayer that your GTM container can consume.
Connecting
Integrations → Google Tag Manager → Connect. The form is a single field:
- GTM Container ID — looks like
GTM-XXXXXX. Found in your GTM workspace at the top of the page.
That's it. No OAuth, no token exchange. The container ID is stored encrypted alongside other integration credentials (for consistency, even though container IDs are not strictly secret).
The integration validates by hitting Google's GTM CDN with the container ID to confirm it loads. A 404 means the container doesn't exist or you typed it wrong.
What gets injected
When the public form (/f/{hash}/{slug}) loads, the backend includes school.gtm_container_id in the form payload. The frontend PublicForm.vue reads it and injects two snippets:
Head:
html
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-XXXXXX');</script>Body (noscript fallback):
html
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>This is the standard GTM snippet — identical to what you'd paste into a static HTML site.
dataLayer events
The form pushes three events that you can wire up in GTM:
| Event | When fired | Payload |
|---|---|---|
kp_form_loaded | Form mounts (after JSON loaded) | { event: 'kp_form_loaded', form_id, kindergarten_id } |
kp_step_advanced | User clicks Next on a multi-step form | { event: 'kp_step_advanced', step, form_id } |
kp_form_submitted | Submission successful | { event: 'kp_form_submitted', form_id, lead_id } |
In GTM, set up a Custom Event Trigger matching kp_form_loaded (or others) and bind it to whichever tag you want — GA4, Meta Pixel, TikTok Pixel, LinkedIn Insight, etc.
No per-pixel UI is shipped in Kinderpedia. Everything happens via GTM's no-code interface.
Example: GA4 + Meta Pixel
A common setup:
- Add Google Analytics: GA4 Configuration tag in GTM. Trigger on All Pages.
- Add Google Analytics: GA4 Event tag named
Form Submission. Event namegenerate_lead. Trigger on Custom Eventkp_form_submitted. - Add Meta Pixel custom HTML tag (Meta's snippet). Trigger on All Pages.
- Add Meta Pixel Event custom HTML tag firing
fbq('track', 'Lead'). Trigger on Custom Eventkp_form_submitted.
Publish the GTM container. From the next form load onwards, every conversion fires both GA4 and Meta Pixel — without you touching Kinderpedia code.
Per-school isolation
Each school has its own GTM container ID. Schools never see each other's tracking. If school A and school B both connect GTM, they're independent — A's tags don't fire on B's forms.
Privacy + consent
Kinderpedia doesn't implement consent banners. If your jurisdiction (EU, California, etc.) requires consent before loading tracking pixels, you must handle that yourself — usually via a Consent Mode v2 setup in GTM, or a separate consent banner that conditionally publishes the container.
Don't connect GTM and ignore consent regulations — it's your platform / your jurisdiction.
Disconnecting
Disconnect clears the container ID. The next form load won't inject GTM. Existing visitor sessions in-flight (already loaded the form) continue using the injected GTM until they navigate away.
Common errors
| Symptom | Likely cause |
|---|---|
| Connect rejects with "container not found" | Typo'd Container ID, or container was deleted. |
| GTM Preview shows form events but production doesn't | Container not published — events fire only in Preview Mode until you Publish. |
| GA4 missing form events | Custom Event trigger in GTM doesn't match the event name (kp_form_submitted exact). |
| Pixel firing twice | Multiple GTM containers loaded — only one Kinderpedia GTM allowed. |
What this is NOT
- Not a way to track parents inside the dashboard (
/dashboard,/leads) — only public forms are tracked. - Not a way to embed custom HTML / JavaScript outside of GTM's tag mechanisms — for that, build a custom integration.
- Not a CRM analytics tool — for funnel reporting, use the built-in Reports module.