> Site index: https://usehardal.com/llms.txt
> Every content route also serves markdown at <url>.md

# Track Event Campaigns with QR Codes and Server-Side Tagging

Connect ticket purchases to QR code scans at event gates with server-side Google Tag Manager, first-party campaign data, and a reliable ticket_scan event.

Source: https://usehardal.com/track-event-campaigns-with-qr-codes-and-server-side-tagging
Published: 2024-08-16
Updated: 2026-09-27
Author: Berkay Demirbas
Category: Server-Side Tracking

---

A ticket purchase tells you which campaign generated revenue. A QR scan at the gate tells you whether that ticket became an attended event. Connect the two to compare campaign-driven sales with actual attendance.

Server-side Google Tag Manager can receive the scan from a gate application, enrich it with first-party purchase data, and route the resulting event to your analytics or advertising destinations.

Consider a music festival that sells tickets on its website. The purchase record stores the campaign parameters captured during the buying session. Each ticket gets a QR code, and staff scan that code at the venue entrance.

The QR code should contain an opaque ticket token, not an email address, phone number, or full customer record. When the scanner sends that token to your backend, the backend resolves it to the ticket and purchase data it already holds.

The flow looks like this:

1. The visitor arrives through a campaign and buys a ticket.
2. Your backend saves the ticket ID with its campaign attribution.
3. The ticketing system generates a QR code with an opaque token.
4. The gate scanner sends the token and scan details to a first-party endpoint.
5. The endpoint validates the ticket and forwards a `ticket_scan` event to the server container.
6. Server-side tags send the approved fields to your reporting destinations.

This creates a measurable path from campaign click to purchase to attendance.

After the backend resolves the QR token, the event could use this structure:

```json
{
  "event": "ticket_scan",
  "event_id": "scan_01J8Y6Q3M4K2P7",
  "event_time": "2026-09-27T18:42:12.000Z",
  "ticket_id": "ticket_78910",
  "user_id": "user_123456",
  "gate_id": "north_gate_04",
  "utm_source": "facebook",
  "utm_medium": "paid_social",
  "utm_campaign": "autumn_festival"
}
```

`event_id` makes the scan idempotent. If a scanner retries the request after a weak network response, your collection layer can reject the duplicate instead of recording a second attendance event.

Choose what a scan means before building reports. The first accepted scan may count as attendance, while later scans can represent re-entry, a rejected ticket, or a support case. Those outcomes should use explicit fields or separate event names.

The scanner application can post the resolved event to an endpoint on your own domain:

```js
async function sendTicketScan(scan) {
  const response = await fetch('https://collect.example.com/ticket-scan', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      event: 'ticket_scan',
      event_id: scan.eventId,
      event_time: new Date().toISOString(),
      ticket_id: scan.ticketId,
      gate_id: scan.gateId
    })
  });

  if (!response.ok) {
    throw new Error(`Ticket scan failed with ${response.status}`);
  }
}
```

Authenticate the scanner, validate the payload, and apply rate limits at the collection endpoint. Do not trust a ticket ID because it arrived from a device at the gate.

If the endpoint points directly to a server-side GTM container, configure a client that claims the request path and converts the body into event data. You can also receive the request in your own backend or through Hardal, validate it there, then forward the clean event to sGTM.

The campaign parameters do not need to live inside the QR code. Save them with the purchase, then join them when the scan arrives. That keeps the code small and prevents a customer from changing attribution values before entry.

With purchase and attendance events in the same first-party data model, you can answer questions that ticket sales alone cannot:

- Which campaigns produced the most attendees?
- Which campaigns had the highest no-show rate?
- How long passed between purchase and attendance?
- Did a promotion sell tickets that were transferred or refunded before the event?
- Which gates and time windows handled the most arrivals?

The same pattern works for conferences, sports venues, pop-up shops, and any offline checkpoint linked to an online transaction.

Keep the gate payload narrow. A scanner usually needs a ticket token, gate ID, timestamp, and scan result. Resolve customer and campaign data on the server, where access controls and retention rules are easier to enforce.

Plan for unreliable venue networks. Queue scans locally with a unique event ID, retry them when the connection returns, and record whether the gate admitted the ticket. Test the full path before doors open, including duplicate scans and offline recovery.

- [Google: Send data to server-side Tag Manager](https://developers.google.com/tag-platform/tag-manager/server-side/send-data)
- [Google: An introduction to server-side tagging](https://developers.google.com/tag-platform/tag-manager/server-side/intro)
- [Hardal server-to-server endpoint guide](https://usehardal.com/server-to-server-endpoint)
