Skip to content

feat: add organizer tracking pixels with cookie consent#1166

Merged
daveearley merged 10 commits intodevelopfrom
feat/tracking-pixels
Apr 18, 2026
Merged

feat: add organizer tracking pixels with cookie consent#1166
daveearley merged 10 commits intodevelopfrom
feat/tracking-pixels

Conversation

@daveearley
Copy link
Copy Markdown
Contributor

Allow organizers to configure tracking pixels (Facebook Pixel, Google Analytics 4, Google Tag Manager, TikTok Pixel) for their public event pages, organizer homepage, and checkout flow. Pixels are gated behind a cookie consent banner that respects GDPR requirements.

  • Backend: migration, enum, DTO, validation with provider-specific format rules, public resource strips sensitive fields
  • Frontend: plugin architecture with 4 providers, consent manager with Google Consent Mode v2, cookie consent banner component
  • Settings UI: fixed provider cards with icons, enable/disable toggles, format validation, GDPR acknowledgment
  • Funnel events: PageView, ViewContent, InitiateCheckout, Purchase with transaction_id for GA4 deduplication
  • Purchase event deduplication via sessionStorage
  • Env vars: VITE_COOKIE_CONSENT_ENABLED, VITE_COOKIE_CONSENT_TEXT

Allow organizers to configure tracking pixels (Facebook Pixel, Google
Analytics 4, Google Tag Manager, TikTok Pixel) for their public event
pages, organizer homepage, and checkout flow. Pixels are gated behind
a cookie consent banner that respects GDPR requirements.

- Backend: migration, enum, DTO, validation with provider-specific
  format rules, public resource strips sensitive fields
- Frontend: plugin architecture with 4 providers, consent manager
  with Google Consent Mode v2, cookie consent banner component
- Settings UI: fixed provider cards with icons, enable/disable
  toggles, format validation, GDPR acknowledgment
- Funnel events: PageView, ViewContent, InitiateCheckout, Purchase
  with transaction_id for GA4 deduplication
- Purchase event deduplication via sessionStorage
- Env vars: VITE_COOKIE_CONSENT_ENABLED, VITE_COOKIE_CONSENT_TEXT

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app
Copy link
Copy Markdown

railway-app bot commented Apr 15, 2026

🚅 Deployed to the Hi.Events-pr-1166 environment in Hi.Events

Service Status Web Updated (UTC)
Hi.Events API ◻️ Removed (View Logs) Web Apr 15, 2026 at 8:49 pm
Hi.Events Frontend ◻️ Removed (View Logs) Web Apr 15, 2026 at 8:49 pm
1 service not affected by this PR
  • Maildev

@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 15, 2026 20:27 Destroyed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@daveearley daveearley closed this Apr 15, 2026
@daveearley daveearley reopened this Apr 15, 2026
@github-actions github-actions bot locked and limited conversation to collaborators Apr 15, 2026
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 15, 2026 21:04 Destroyed
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 15, 2026 21:12 Destroyed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 17, 2026 06:31 Destroyed
GA4 was not sending data because consent default was skipped when
consent was already granted, causing gtag.js to have no consent
state before config. Now sets consent default to granted/denied
based on existing cookie state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 17, 2026 11:39 Destroyed
gtag.js expects Arguments objects in dataLayer, not Arrays. Using
rest params (...args) and pushing the array caused gtag.js to
process commands but never send g/collect requests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 17, 2026 11:53 Destroyed
Google's standard GTM install pushes the gtm.start event to
dataLayer before injecting the gtm.js script tag. We had
the order reversed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 17, 2026 14:45 Destroyed
GTM allows arbitrary JavaScript execution, which is a security risk
on hosted/SaaS platforms. GTM is now blocked when saas_mode is
enabled:

- Backend: validation rejects GTM provider with clear error message
- Frontend: GTM hidden from provider list, stripped from form
  submission in SaaS mode

Other providers (FB Pixel, GA4, TikTok) are safe as they only
accept pixel IDs and inject known vendor scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 17, 2026 15:40 Destroyed
- Update cookie consent text to be more informative and GDPR-compliant
- Add Privacy Policy link using existing VITE_PRIVACY_URL config
- Fix Google Consent Mode v2 race condition (init before scripts load)
- Fix SSR hydration mismatch by deferring consent state read to mount
- Fix ViewContent/Purchase events not firing after consent granted
- Add GTM re-initialization guard to prevent duplicate script tags
- Add error handling for failed tracking pixel initialization
- Add backend validation requiring consent acknowledgment for enabled pixels
- Add translations for cookie banner strings across all locales
- Add unit tests for pixel ID validation and request validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 18, 2026 11:20 Destroyed
Prevents GTM pixel IDs from being returned via public organizer/event
endpoints when SaaS mode is enabled, closing a gap where pre-existing
GTM entries could still be loaded and executed on the frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to Hi.Events / Hi.Events-pr-1166 April 18, 2026 11:25 Destroyed
@daveearley daveearley merged commit 3109cad into develop Apr 18, 2026
7 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant