Przejdź do głównej zawartości

Śledzenie skanowań i analityka

Przegląd

Każde skanowanie dynamicznego kodu QR generuje rekord skanowania (Scan-Record) w Twoim Workspace. Rejestracja odbywa się w całości na Cloudflare Edge — bez zewnętrznych usług śledzących, bez plików cookie i bez sytuacji, w której oryginalny adres IP kiedykolwiek trafia do Twojej bazy danych.

Trzy sposoby na korzystanie z danych skanowania:

API agregacji

GET /v1/codes/:id/scans — szeregi czasowe + najpopularniejsze kraje/urządzenia/systemy operacyjne dla pojedynczego obiektu kodu.

Webhooki (w czasie rzeczywistym)

Zdarzenie qr.scanned dla każdego skanowania, podpisane HMAC-SHA256. Zobacz Webhooki.

Panel (Dashboard)

Wizualizacja w panelu qr3.app — bez konieczności wywoływania API.


Jakie dane są gromadzone

Dla każdego skanowania tworzony jest rekord w tabeli scans:

PoleŹródłoPrzykład
idUUID wygenerowane przez serwerscn_d1f8…
code_idID skanowanego kodu QRqr_a1b2c3d4
workspace_idWorkspace koduws_xxx
countryCloudflare cf.countryAT
regionCloudflare cf.regionVienna
cityCloudflare cf.cityWien
device_typeParsowanie User-Agentmobile, tablet, desktop
osParsowanie User-AgentiOS, Android, macOS, Windows
browserParsowanie User-AgentSafari, Chrome, Firefox
refererNagłówek HTTP Refererhttps://example.com/landing
languageNagłówek Accept-Language (pierwszy język)de
redirected_toRzeczywisty cel przekierowaniahttps://example.com
ip_hashDzienny pseudonim HMAC-SHA-256 (długotrwały sekret + cel + dzień UTC + IP)8f3a…
scanned_atZnacznik czasu ISO-86012026-05-12T14:32:11.000Z

Geolokalizacja na brzegu sieci (Edge)

Wszystkie dane geograficzne (country, region, city) pochodzą z obiektu cf platformy Cloudflare i bazują na bazie danych Geo-IP Cloudflare. Nie są wysyłane zapytania do zewnętrznych usług Geo-IP — ustalanie lokalizacji odbywa się w tym samym Workerze, który wykonuje przekierowanie.

Ma to trzy konsekwencje:

  1. Niskie opóźnienie — brak dodatkowego przeskoku (hop) i brak zapytania DNS do zewnętrznego dostawcy.
  2. Ochrona danych — adres IP nie opuszcza Cloudflare i nigdy nie jest przekazywany podmiotom trzecim.
  3. Ograniczona szczegółowośćcity nie zawsze jest dostępne (np. w przypadku sieci VPN, operatorów komórkowych lub małych regionów). Należy spodziewać się wartości null i uwzględnić je w swoich panelach.

Odpytywanie analityki skanowań

GET /v1/codes/:id/scans

Zwraca zagregowane dane analityczne dla pojedynczego kodu QR w wybranym okresie.

Okno terminala
curl "https://qr3.app/v1/codes/qr_a1b2c3d4/scans?days=30" \
-H "Authorization: Bearer qr3_sk_..."

Parametry zapytania (Query Parameters):

ParametrTypDomyślnieOpis
daysinteger30Okres w dniach (1–365)

Odpowiedź (HTTP 200):

{
"data": {
"code_id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"total_scans": 1842,
"period_days": 30,
"period_scans": 367,
"scans_by_day": [
{ "date": "2026-04-13", "count": 12 },
{ "date": "2026-04-14", "count": 18 }
],
"top_countries": [
{ "value": "AT", "count": 142 },
{ "value": "DE", "count": 98 },
{ "value": "CH", "count": 41 }
],
"top_devices": [
{ "value": "mobile", "count": 281 },
{ "value": "desktop", "count": 72 },
{ "value": "tablet", "count": 14 }
],
"top_os": [
{ "value": "iOS", "count": 158 },
{ "value": "Android", "count": 123 },
{ "value": "macOS", "count": 48 }
]
},
"meta": { "request_id": "req_xyz123" }
}

Pola odpowiedzi:

PoleOpis
total_scansCałkowita liczba skanowań kodu od momentu utworzenia (niezależnie od okna days)
period_scansSuma skanowań w wybranym oknie czasowym
scans_by_dayDzienne przedziały (buckets), rosnąco według daty, puste dni są pomijane
top_countriesTop 8 krajów w oknie czasowym, malejąco
top_devicesTop 5 typów urządzeń (mobile, tablet, desktop)
top_osTop 5 systemów operacyjnych

Agregacja dla wielu kodów

Sumy dla całego Workspace (np. skanowania na miesiąc dla wszystkich kodów) są dostępne za pośrednictwem GET /v1/workspaces/:id w polu scans_this_month. Do analiz między wieloma kodami zalecamy korzystanie z panelu lub okresowego eksportu.


Konsumpcja w czasie rzeczywistym przez webhooki

Jeśli chcesz przetwarzać zdarzenia skanowania natychmiast, gdy się pojawią — na przykład na potrzeby paneli na żywo, śledzenia leadów lub integracji z CRM — zasubskrybuj zdarzenie qr.scanned:

Okno terminala
curl -X POST https://qr3.app/v1/webhooks \
-H "Authorization: Bearer qr3_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/qr3",
"events": ["qr.scanned"],
"secret": "my-secret-key-min-16-chars"
}'

Payload (ładunek danych):

{
"id": "evt_abc123xyz",
"type": "qr.scanned",
"created": "2026-05-12T14:32:11.000Z",
"data": {
"code_id": "qr_a1b2c3d4",
"short_code": "r7f3Kx",
"scan_id": "scn_d1f8...",
"country": "AT",
"device_type": "mobile",
"os": "iOS"
}
}

Pełna dokumentacja dotycząca weryfikacji sygnatury, logiki ponawiania prób i logów dostarczenia znajduje się w sekcji API → Webhooks.


RODO i ochrona danych

Rekordy skanowania nie przechowują oryginalnego IP. Edge Worker wyprowadza pseudonim HMAC-SHA-256 z długotrwałego sekretu, celu i dnia UTC; pseudonim pozostaje daną osobową.

  • Bez sekretu wartość nie jest bezpośrednio odwracalna, ale posiadacz sekretu może ponownie obliczyć znane kandydaty IP dla dnia UTC.
  • Cel i dzień UTC są częścią wyprowadzenia, więc hashe tego samego skanera w różnych dniach nie są bezpośrednio porównywalne.
  • Oryginalny IP nie trafia do D1, KV ani R2.

W oknach wielodniowych unique_scanners to metryka Dni skanowania, a nie osób: ten sam skaner otrzymuje osobny pseudonim dla każdego dnia UTC.

Okres przechowywania (Retention) zależy od planu:

PlanOkres przechowywania
Free7 dni
Pro90 dni
Business / Agency1 rok
EnterpriseNiestandardowy (SLA)

Uruchamiane codziennie zadanie cron (purgeOldScans) automatycznie usuwa starsze rekordy — nie wpływa to na wartość total_scans w obiekcie kodu.


Dobre praktyki

  • Częstotliwość odpytywania (Polling): API agregacji jest wydajne, ale nie jest przeznaczone do odpytywania co sekundę. Do aktualizacji na żywo zawsze preferuj webhooki, a API używaj tylko do uzupełniania danych (backfills) lub paneli.
  • Buforowanie (Caching): Odpowiedź zawiera szeregi czasowe — przy dużych oknach (days=365) ładunek danych może mieć rozmiar kilku KB. Buforuj dane po stronie klienta z krótkim czasem życia (TTL, np. 60 s).
  • Limity Top-N: Pola top_countries, top_devices, top_os są ograniczone po stronie serwera odpowiednio do 8 lub 5 wpisów. W celu przeprowadzenia głębszych analiz wyeksportuj surowe dane.
  • Tolerowanie wartości null: Pola country, region, city, referer, language mogą mieć wartość null. W swoich analizach traktuj je jako „Nieznane” (Unknown).