Analytics & Traffic

How traffic, channels, campaigns and conversion are measured in Kickets — for organizers and the Kickets team.

The Analytics tab inside each event shows real visitor traffic to your public event page, broken down by marketing channel and campaign, with a conversion percentage to paid orders. Everything is aggregated and anonymous — no visitor IDs, sessions, IPs or user-level data are ever exposed in the UI or in exports.

Organizer Guide

What the Traffic section shows

Open any event → Analytics tab → Traffic card. You'll see five KPIs across the top:

Page viewsevery visit to your public event page (deduped per browser tab).
Unique visitorsdistinct anonymous browsers in the selected range.
Returning visitorsvisitors that came back across multiple sessions.
Sessionstotal browsing sessions (a session ends after inactivity).
Purchase conversion %paid orders ÷ tracked page views in the date range.

Channels and campaigns (UTM)

Every link you share should include UTM parameters so we can tell where your buyers came from. Use the UTM Link Builder in the Analytics tab to generate them quickly.

Example link:

https://kicketsctrl.com/e/your-event?utm_source=instagram
  &utm_medium=social
  &utm_campaign=launch_week

That URL feeds two breakdowns:

By channelSource × Medium (e.g. instagram / social) with views, visitors, orders, revenue and conversion %.
By campaigncampaign name (e.g. launch_week) with views, visitors, orders, revenue and conversion %.

Visitors who arrive without UTM tags are grouped as direct / (none).

Choosing a date range

Use the range buttons in the top-right of the Traffic card:

7 daysshort-term campaign reads.
30 daysdefault; good balance for ongoing sales.
90 dayslong lead-time festivals and slow-build sales.
Allevery recorded visit since tracking began.

Conversion % is always computed against the same window as the views: paid orders divided by tracked page views inside the range.

Exporting traffic data (CSV)

Click Export CSV in the Traffic card to download an aggregated report. The file contains:

  • A header with the selected range, currency, and generation timestamp.
  • One row per channel: Source, Medium, Views, Visitors, Orders, Revenue, Conversion %.
  • One row per campaign: Campaign, Views, Visitors, Orders, Revenue, Conversion %.

The export never contains visitor IDs, session IDs, user IDs, IP addresses, or raw page-view rows. It is safe to share with collaborators or paste into a spreadsheet.

What we don't track

  • No personal identifiers in the dashboard or in exports.
  • No cross-event browsing — each event has its own traffic feed.
  • Marketing pixels (Meta, GA4, GTM, TikTok) only fire after the visitor accepts the consent banner.

Sales Intelligence

Below the Traffic card, the Sales section shows the commercial picture of your event in real money — not page views. All figures are computed server-side from confirmed paid orders and refunds, so what you see here always matches what the Kickets finance team sees.

Gross revenuesum of every paid order (VAT inclusive, before refunds).
Net revenuegross minus refunded amounts. This is the figure that flows into your settlement.
VATFinnish VAT extracted from gross using the inclusive formula (13.5% tickets, 25.5% merch).
Tickets soldpaid ticket units. VIP tables and merch are counted separately.
Per-product breakdownrevenue, units sold and average price for every product on the event.

Reservations that haven't been paid yet are not counted in revenue. They show up in Inventory as reserved so you can see committed inventory.

Refund Analytics

The Refunds section breaks down what was returned to buyers and why. It does not expose any buyer identity — just totals, splits and reasons.

Total refundedsum of every refunded line (full and partial combined).
Full vs partial splitpartial refunds only count as “full” once every unit on the order is refunded.
By reasonduplicate, customer request, cancelled event, fraud, other. Use this to spot patterns.
By productwhich ticket types or add-ons are being returned most.

Refunds flow through your accounting automatically — you don't need to log them anywhere else.

Inventory Analytics

The Inventory section is the commercial view of what's left to sell. It is a different thing from the door / scanner occupancy panel — that one is about who's physically inside the venue.

Sell-through %sold ÷ total capacity, per product and overall.
Availableunits still buyable right now (total minus sold minus actively reserved).
Status badgeshealthy, low, sold_out, inactive, unlimited.
Warningsfor example over_capacity when the total sellable across products exceeds the venue's physical capacity. Use the Venue Capacity card on the Overview tab to confirm or override capacity.

Refunded units are returned to available automatically — you don't need to re-open the tier yourself.

Live updates

Sales, Refunds and Inventory numbers update on their own while you're looking at the page. There's no Refresh button to babysit on launch night.

  • New paid orders trigger a refresh within about a second.
  • A polling fallback runs every 15 seconds, so even on flaky networks you're never more than 15 seconds behind.
  • Each card shows a small Updated HH:MM:SS timestamp so you can confirm freshness at a glance.

The Traffic card is the one exception — it updates when you change the date range or click Refresh, because page-view rollups are heavier than order rollups.

Export Center

At the bottom of the Analytics tab is the Export Center — one place to download every report for this event as CSV. All exports use the same format (UTF-8, Excel-safe, RFC 4180 escaping) and include a header with the event, date range and generation timestamp.

Sales summarygross, net, VAT, commission, refunds, fees, paid order count.
Productsrevenue, units, average price per product.
Refundsevery refunded line with reason and amount.
Inventoryper-product total, sold, reserved, refunded, available, sell-through %, status.
Trafficchannel × medium and campaign breakdowns with conversion %.
Buyers / Ordersflattened order rows with attribution, suitable for CRM import.
Scan auditevery gate-side scan with timestamp, gate, device and result.

Buttons you don't have permission to use are shown as “Not available for your role” rather than hidden, so you can see what exists and request access from the workspace owner. PDF exports are marked “Coming later” — until then, open the CSV in Numbers, Excel or Google Sheets and print to PDF from there.

Promoter Playbook

What to look at, and when

Analytics only helps if you check it at the right moments. Here is the rhythm that works for most events on Kickets.

T-30 days — on-sale week. Watch Traffic → by channel. If Instagram is sending traffic but conversion is under 1%, the lowest tier isn't visible enough or the page isn't loading the scarcity cue. Adjust the hero, not the price.
T-14 days — second push. Compare Sales → tickets sold with Inventory → sell-through %. If you're under 30% sell-through, this is the moment to open an affiliate campaign or launch a promo code — not the week of the event.
T-7 days — urgency window. Watch Live updates on Sales. Refunds spiking here usually means a date / venue / lineup confusion. Check Refund Analytics → by reason before pushing more ads.
Event day. Switch to the Live Occupancy panel (Gate / Scanning tab). The Analytics tab is a money lens; occupancy is a door lens. Don't use Sales to decide whether to open the gates.
T+3 days. Pull the Buyers / Orders CSV into your CRM and the Sales summary CSV into your bookkeeping. Settlement happens automatically — you don't need to reconcile by hand.

Tag every link you share

The single biggest unlock in Analytics is also the simplest: never share a raw event URL. Use the UTM Link Builder at the top of the Analytics tab to generate a tagged link for every place you post.

Instagram bio linkutm_source=instagram&utm_medium=bio
Instagram story stickerutm_source=instagram&utm_medium=story
Newsletterutm_source=newsletter&utm_medium=email&utm_campaign=announcement
Paid Meta adutm_source=meta&utm_medium=cpc&utm_campaign=launch_week
Influencer postuse an affiliate link instead — you get UTM + commission tracking automatically.

A tag you didn't set will simply show up as direct / (none), which means “I have no idea where this buyer came from.”

Who can see what

Analytics respects the role you were granted in this workspace. The matrix below is what each role sees on this Analytics tab.

RoleSales / RefundsInventoryTrafficBuyersScan audit
Owner / AdminYesYesYesYesYes
FinanceYesYesNoYesYes
Event managerNoYesNoNoYes
MarketingNoNoYesNoNo
Support (read-only)NoNoNoYesNo
Scanner / Door opsNoNoNoNoNo

See Security for the full role model and how to invite teammates.

Frequently asked questions

Why is my Sales number different from Stripe?

Kickets reports gross revenue including VAT. Stripe reports net of refunds. Net revenue in Kickets is the figure that should match your Stripe balance for the period.

Why do reservations not count toward revenue?

Reservations are 10-minute holds, not sales. They release automatically if the buyer doesn't complete checkout. You can see them under reserved in Inventory.

Why is Traffic empty on a brand new event?

Traffic only starts recording once the event is published and the first visitor accepts the consent banner. Until then the page exists but isn't broadcast.

Where did the “Export PDF” button go?

We removed it because the implementation was incomplete. PDF exports will return in a future release. For now, open any CSV in Numbers / Excel / Google Sheets and print to PDF.

Technical Reference

Data model

event_page_viewsone row per public event-page visit. Stores event_id, visitor_id, session_id, optional user_id, UTM fields (utm_source/medium/campaign/content/term), referrer_url, referrer_domain, landing_path, device_type, viewed_at.
orderscaptures attribution at checkout via utm_source, utm_medium, utm_campaign, session_id, attributed_channel, attributed_at.
Row-Level Securityrestricts event_page_views SELECT to the event's organizer, assigned team members (marketing/event_manager/admin/owner/finance) and platform admins. Inserts are open (anonymous tracking).

RPC: get_event_traffic_metrics(event_id, days)

The Traffic UI is fed by a single Postgres RPC that returns:

totalspage_views, unique_visitors, returning_visitors, sessions.
ordersorders_count and revenue inside the window.
by_channelarray of { source, medium, views, visitors, orders, revenue, conversion_rate }, joined to orders on matching utm_source + utm_medium.
by_campaignarray of { campaign, views, visitors, orders, revenue, conversion_rate }, joined to orders on matching utm_campaign.

A FULL OUTER JOIN ensures channels with traffic but no sales (and sales without traffic) are both surfaced.

Known limitation: paid_at vs created_at

The RPC currently uses orders.created_at as the paid-order timestamp. This is acceptable today because orders are only created after a successful Stripe charge, so created_at ≈ paid time.

When full Stripe webhook finalization ships (orders may be created pre-payment and finalized async), we will add an orders.paid_at column populated by the webhook and switch the RPC + UI to use:

COALESCE(paid_at, created_at)

Privacy and PII boundaries

  • UI: never renders visitor_id, session_id, user_id, or IP.
  • CSV export: only aggregated channel/campaign rows + range, currency, timestamp metadata.
  • Pixels: gated by consent. See the consent banner in Trust & Data Protection.