feat: measure clicks through to the ticket shop - #18
Merged
Merged
Conversation
GA4 reports how people arrive and which pages they read, but nothing about the step that matters most: leaving for the Pretix shop. Add a select_ticket_link event so that intent is visible. The event is custom rather than begin_checkout because the purchase happens on Pretix and we never learn whether it completed; feeding it into the ecommerce funnel would invent a funnel we cannot close. Mark it as a key event in the GA4 UI to count it as a conversion. One delegated listener rather than a handler per link: ticket links appear in the header, the home hero, the ticket cards, navigation.json and the Markdown content, so matching on the shop host means a link added later is measured with no extra work. The host is a setting so there is a single thing to change, and so a staging shop still reports. Traffic source is deliberately not attached. GA4 resolves source, medium and campaign for the session, so the event already carries the attribution of the visit it belongs to; only the source page and the destination, which GA4 cannot know, are passed. The hit goes out by beacon because the click navigates away and a normal request would be cancelled in flight. Nothing is measured without consent: the listener returns early when the tag was never loaded, so a visitor who declines is still not tracked and no request reaches Google. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011i8AYdEkHBURzkFmyGpQmy
Pins the parts that are easy to break silently: the tracker ships only when a measurement ID is configured, it matches the configured shop host, it sends by beacon, and it stays off the ecommerce funnel events. The last test is the one that earns its keep. The tracker matches on the host, so a ticket link edited to point somewhere else would simply stop being measured with nothing failing; asserting the home page links to the configured host turns that into a red test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011i8AYdEkHBURzkFmyGpQmy
The privacy guide describes what analytics collects, so it has to mention the new event. States the limit as well as the fact: we see that a link was followed, never whether a purchase was made, and a visitor who declines is not measured at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011i8AYdEkHBURzkFmyGpQmy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a
select_ticket_linkGA4 event fired when a visitor follows any link to the Pretix ticket shop, so we can see which pages and which traffic sources actually lead people to tickets.Why not
purchaseorbegin_checkoutThe purchase happens on Pretix and we never learn whether it completed, so a purchase event would be a claim we cannot support.
begin_checkoutwas rejected for the same reason at one remove: it flows into GA4's ecommerce funnel reports and would invent a funnel with a permanently missing bottom. A custom event keeps the reports honest. There is a test pinning this.To count it as a conversion, mark it as a key event in the GA4 UI — no code change needed.
How
One delegated listener on the document rather than a handler per link. Ticket links appear in the header, the home hero, the four ticket cards,
navigation.jsonand the FAQ Markdown; matching on the shop host means a link added later, including one written in content, is measured with no extra work.PRETIX_HOSTis a setting so there is a single thing to change, and so a staging shop still reports.transport_type: 'beacon', because the click navigates away and a normal request would be cancelled in flight.source_pageand the destination — which GA4 cannot know — are passed.Privacy
No change to the consent posture. The listener returns early when the tag was never loaded, so a visitor who declines is not measured and no request reaches Google — the promise the privacy guide already makes. The guide is updated to state what is now recorded and its limit.
Counting clicks from visitors who decline was considered and dropped: GA4's Measurement Protocol requires a
client_id, and a random one per click manufactures a fake user each time, corrupting user and session counts. A server-side counter was the alternative, butbase.pystates plainly that the site has no database, and this did not seem worth reversing that for. Consequence worth knowing when reading the numbers: ticket-click counts undercount by roughly the decline rate, so they are sound for comparing channels rather than as an absolute measure of interest.Testing
begin_checkoutturns two of them red.evil-pretix.evolutio.pt.attacker.com) is correctly rejected.test_the_home_page_actually_links_to_that_hostis the test that earns its keep: the tracker matches on the host, so a ticket link edited to point elsewhere would silently stop being measured — this turns that into a red test.Follow-up in the GA4 UI (not code)
Custom dimensions are not retroactive, so this is worth doing right after deploy or the parameters read
(not set)forever. Under Admin → Custom definitions, registerlink_url,link_textandsource_pageas event-scoped dimensions.🤖 Generated with Claude Code
https://claude.ai/code/session_011i8AYdEkHBURzkFmyGpQmy