First-Party Tracking mit Cloudflare Pages
Richten Sie einen First-Party Proxy mit Cloudflare Pages Functions ein. Dies ist die beste Option, wenn Sie Ihre Website bereits auf Cloudflare Pages hosten.
Schwierigkeitsstufe: Einfach - Fügen Sie einfach eine Datei zu Ihrem Projekt hinzu. Dauert etwa 5 Minuten.
Warum das funktioniert (Same-Origin)
Dieser Ansatz verwendet /api/_z/script.js, das sich auf der gleichen Origin wie Ihre Website befindet. Firefox ETP und andere Tracking-Schutzmaßnahmen blockieren nur Cross-Origin-Anfragen.
- Browser sieht:
yourdomain.com/api/_z/script.js→ Same Origin ✅ - Ihre Funktion leitet die Anfrage Server-zu-Server an den Zenovay-Server weiter (Browser sieht das nie)
- Der gesamte Tracking-Schutz wird umgangen, da es sich um eine First-Party-Anfrage handelt
Vorbereitung
Stellen Sie sicher, dass Sie folgendes haben:
- Ein Projekt, das auf Cloudflare Pages bereitgestellt ist
- Ihren Zenovay Tracking-Code (zu finden unter Domains, öffnen Sie Ihre Website und gehen Sie dann zum Tab General — in der Tracking-Script-Karte)
- Zugriff auf den Quellcode Ihres Projekts
Format Ihres Tracking-Codes
Ihr Tracking-Code sieht so aus: ZV_XXXXXXXXXX
- Beginnt mit
ZV_ - Gefolgt von 10 Zeichen (Buchstaben und Zahlen)
- CASE-SENSITIVE - kopieren Sie ihn exakt
Beispiel: ZV_Q8U0GYD70WR

Wie es funktioniert
Wenn Sie einen functions-Ordner zu Ihrem Cloudflare Pages Projekt hinzufügen, erstellt Cloudflare automatisch serverlose Funktionen. Wir erstellen eine Funktion, die Anfragen an die Zenovay-API weiterleitet und sie so für Browser als First-Party-Anfragen erscheinen lässt.
Browser → yourdomain.pages.dev/api/_z/script.js ✅ (First-Party)
↓
Cloudflare Function
↓
api.zenovay.com/fp/script.js (Server-zu-Server)
Schritt 1: Erstellen Sie das Functions-Verzeichnis
Dateispeicherort ist KRITISCH
Der functions-Ordner MUSS sich im Wurzelverzeichnis Ihres Projekts befinden. Nicht in src/, nicht in public/.
Korrekte Position:
your-project/
├── functions/ ← HIER (Projektwurzel)
│ └── api/
│ └── _z/
│ └── [[path]].ts
├── src/
├── public/
└── package.json
FALSCHE Positionen:
- ❌
src/functions/api/_z/[[path]].ts- Funktionen funktionieren nicht - ❌
public/functions/api/_z/[[path]].ts- Funktionen funktionieren nicht
Erstellen Sie die Verzeichnisstruktur:
# Erstellen Sie die Functions-Verzeichnisstruktur
mkdir -p functions/api/_z
# Überprüfen Sie, ob Sie am richtigen Ort sind
ls -la
# Sie sollten sehen: functions/ src/ public/ package.json etc.Nach dem Ausführen dieser Befehle sollte Ihre Projektstruktur so aussehen:
your-project/
├── functions/
│ └── api/
│ └── _z/
│ └── [[path]].ts ← Wir werden das später erstellen
├── src/
├── public/
├── package.json
└── ...
Schritt 2: Erstellen Sie die Proxy-Funktion
Dateibenennung ist WICHTIG
Die Datei MUSS den Namen [[path]].ts haben (oder [[path]].js für JavaScript):
- Zwei öffnende Klammern:
[[ - Das Wort
path - Zwei schließende Klammern:
]] - Dateierweiterung:
.tsoder.js
Dies erstellt eine "Catch-All"-Route, die jeden Pfad nach /api/_z/ verarbeitet.
TypeScript oder JavaScript?
- Verwenden Sie
.ts, wenn Ihr Projekt TypeScript verwendet - Verwenden Sie
.js, wenn Ihr Projekt JavaScript verwendet - Beide funktionieren auf genau die gleiche Weise
Falls unsicher, versuchen Sie zunächst .ts. Wenn Sie TypeScript-Fehler beim Build erhalten, benennen Sie die Datei stattdessen in .js um.
Erstellen Sie die Datei functions/api/_z/[[path]].ts mit diesem Inhalt:
/**
* Zenovay First-Party Proxy
* Diese Funktion leitet Tracking-Anfragen weiter, um sie First-Party zu machen
*/
interface EventContext {
request: Request
params: { path?: string[] }
}
export async function onRequest(context: EventContext): Promise<Response> {
const { request, params } = context
// Pfad aus dem Catch-All-Parameter aufbauen
// [[path]] erfasst: script.js, e/CODE, settings/CODE, etc.
const path = (params.path || []).join('/')
const url = new URL(request.url)
const targetUrl = `https://api.zenovay.com/fp/${path}${url.search}`
// Verarbeiten Sie CORS-Preflight-Anfragen
if (request.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
})
}
try {
// Holen Sie die echte Client-IP für genaue Geolokalisierung
const clientIP = request.headers.get('CF-Connecting-IP') || ''
// Leiten Sie die Anfrage mit echter IP weiter
const proxyHeaders = new Headers(request.headers)
proxyHeaders.set('X-Zenovay-Real-IP', clientIP)
proxyHeaders.delete('Host')
// Bauen Sie die Anfrage auf
const requestInit: RequestInit = {
method: request.method,
headers: proxyHeaders,
}
// Fügen Sie den Body für POST/PUT/PATCH-Anfragen ein
if (['POST', 'PUT', 'PATCH'].includes(request.method)) {
requestInit.body = await request.arrayBuffer()
}
// Leiten Sie an Zenovay weiter
const response = await fetch(targetUrl, requestInit)
// Fügen Sie CORS-Header zur Antwort hinzu
const responseHeaders = new Headers(response.headers)
responseHeaders.set('Access-Control-Allow-Origin', '*')
return new Response(response.body, {
status: response.status,
headers: responseHeaders,
})
} catch (error) {
console.error('Proxy error:', error)
return new Response(JSON.stringify({ error: 'Proxy error' }), {
status: 502,
headers: { 'Content-Type': 'application/json' },
})
}
}JavaScript-Alternative
Wenn Sie lieber JavaScript verwenden (kein TypeScript), erstellen Sie functions/api/_z/[[path]].js:
/**
* Zenovay First-Party Proxy
* Diese Funktion leitet Tracking-Anfragen weiter, um sie First-Party zu machen
*/
export async function onRequest(context) {
const { request, params } = context
// Pfad aus dem Catch-All-Parameter aufbauen
const path = (params.path || []).join('/')
const url = new URL(request.url)
const targetUrl = `https://api.zenovay.com/fp/${path}${url.search}`
// Verarbeiten Sie CORS-Preflight-Anfragen
if (request.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
})
}
try {
// Holen Sie die echte Client-IP für genaue Geolokalisierung
const clientIP = request.headers.get('CF-Connecting-IP') || ''
// Leiten Sie die Anfrage mit echter IP weiter
const headers = new Headers(request.headers)
headers.set('X-Zenovay-Real-IP', clientIP)
headers.delete('Host')
// Leiten Sie an Zenovay weiter
const response = await fetch(targetUrl, {
method: request.method,
headers: headers,
body: ['POST', 'PUT', 'PATCH'].includes(request.method)
? await request.arrayBuffer()
: undefined,
})
// Fügen Sie CORS-Header zur Antwort hinzu
const responseHeaders = new Headers(response.headers)
responseHeaders.set('Access-Control-Allow-Origin', '*')
return new Response(response.body, {
status: response.status,
headers: responseHeaders,
})
} catch (error) {
return new Response(JSON.stringify({ error: 'Proxy error' }), {
status: 502,
headers: { 'Content-Type': 'application/json' },
})
}
}Schritt 3: Fügen Sie das Tracking-Script hinzu
Fügen Sie dieses Script zur HTML Ihrer Website hinzu. Der Speicherort hängt von Ihrem Framework ab:
<!-- Zenovay Analytics - First-Party Tracking -->
<script defer
data-tracking-code="YOUR_TRACKING_CODE"
src="/api/_z/script.js">
</script>Ersetzen Sie YOUR_TRACKING_CODE durch Ihren tatsächlichen Tracking-Code aus dem Zenovay Dashboard (z. B. ZV_Q8U0GYD70WR).
Framework-spezifische Beispiele
React / Next.js
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="/api/_z/script.js"
/>
</head>
<body>{children}</body>
</html>
)
}Vue / Nuxt
<!-- In app.vue -->
<script setup>
useHead({
script: [
{
src: '/api/_z/script.js',
defer: true,
'data-tracking-code': 'YOUR_TRACKING_CODE'
}
]
})
</script>Astro
---
const { title } = Astro.props;
---
<html lang="en">
<head>
<title>{title}</title>
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<slot />
</body>
</html>Einfaches HTML
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
<script defer data-tracking-code="YOUR_TRACKING_CODE" src="/api/_z/script.js"></script>
</head>
<body>
<!-- Your content -->
</body>
</html>Schritt 4: Bereitstellung
Stellen Sie Ihr Projekt auf Cloudflare Pages bereit:
Option A: Mit Git (Empfohlen)
Falls Sie automatische Bereitstellungen von Git haben:
git add .
git commit -m "Add Zenovay first-party tracking"
git pushCloudflare Pages wird automatisch Build und Bereitstellung durchführen.
Option B: Mit Wrangler CLI
# Bauen Sie Ihr Projekt zuerst
npm run build
# Stellen Sie auf Cloudflare Pages bereit
npx wrangler pages deploy ./dist --project-name=your-project-nameErsetzen Sie ./dist durch Ihr Build-Ausgabeverzeichnis (könnte ./out, ./build usw. sein) und your-project-name durch Ihren Cloudflare Pages Projektnamen.
Schritt 5: Überprüfen Sie, ob es funktioniert
Prüfung 1: Functions Tab in Cloudflare
- Gehen Sie zu Cloudflare Dashboard → Pages
- Klicken Sie auf Ihr Projekt
- Klicken Sie auf den Tab Functions
- Sie sollten
api/_z/[[path]]aufgelistet sehen
Sehen Sie die Funktion nicht?
- Stellen Sie sicher, dass der
functions-Ordner im Projektwurzelverzeichnis ist (nicht insrc/) - Stellen Sie sicher, dass die Datei
[[path]].tsoder[[path]].jsheißt - Überprüfen Sie, dass die Bereitstellung erfolgreich abgeschlossen wurde
Prüfung 2: Network Tab im Browser
- Öffnen Sie Ihre bereitgestellte Website
- Drücken Sie F12 (oder Cmd+Option+I auf Mac) um DevTools zu öffnen
- Klicken Sie auf den Tab Network
- Aktualisieren Sie die Seite (Cmd+R oder Ctrl+R)
- Geben Sie im Filterfeld
script.jsein - Suchen Sie nach
/api/_z/script.js
Das sollten Sie sehen:
- Status: 200 ✅
- Domain: Ihre Pages Domain (z. B.
your-project.pages.dev) - Response: JavaScript-Code
Prüfung 3: Firefox Strict Mode (Am Wichtigsten!)
Firefox hat den strengsten Tracking-Schutz. Falls es in Firefox funktioniert, funktioniert es überall.
- Öffnen Sie den Firefox-Browser
- Klicken Sie auf das Menü (☰) → Einstellungen
- Klicken Sie auf Datenschutz & Sicherheit in der linken Seitenleiste
- Wählen Sie unter "Enhanced Tracking Protection" die Option Strict
- Besuchen Sie Ihre Website
- Öffnen Sie DevTools (F12) → Network Tab
- Aktualisieren Sie und überprüfen Sie, dass
/api/_z/script.jsmit Status 200 geladen wird
Prüfung 4: Zenovay Dashboard
- Gehen Sie zu app.zenovay.com und melden Sie sich an
- Klicken Sie auf Ihre Website
- Besuchen Sie Ihre bereitgestellte Website in einem anderen Tab
- Innerhalb von 1-2 Minuten sollten Sie den Besuch in Ihrem Dashboard sehen
Finale Checkliste
Überprüfen Sie, bevor Sie fertig sind, ALL diese Punkte:
- Datei
functions/api/_z/[[path]].tsexistiert im Projektwurzelverzeichnis - Funktion erscheint im Cloudflare Pages Functions Tab
- Script wird unter
/api/_z/script.jsmit Status 200 geladen - Attribut
data-tracking-codeenthält Ihren korrekten Tracking-Code - In Firefox mit Enhanced Tracking Protection auf Strict getestet
- Besuche erscheinen im Zenovay Dashboard
Troubleshooting
Funktion gibt 404 zurück
Ursache: Die Funktionsdatei befindet sich an der falschen Position oder hat den falschen Namen.
Lösung:
- Überprüfen Sie, dass sich die Datei exakt unter
functions/api/_z/[[path]].tsbefindetfunctions-Ordner muss im Projektwurzelverzeichnis sein- Muss Unterverzeichnisse
api/_z/haben - Muss
[[path]].tsmit doppelten Klammern heißen
- Stellen Sie sicher, dass der
functions-Ordner in Ihrer Bereitstellung enthalten ist - Überprüfen Sie den Functions Tab im Cloudflare Dashboard
Funktion gibt 500 zurück
Ursache: Es gibt einen Syntax- oder Runtime-Fehler im Funktionscode.
Lösung:
- Überprüfen Sie die Funktionsprotokolle in Cloudflare auf Fehlerdetails:
- Gehen Sie zu Ihrem Pages Projekt → Functions → Logs
- Überprüfen Sie, dass der gesamte Code korrekt kopiert wurde
- Stellen Sie sicher, dass Sie
onRequestexportieren (nichtexport default)
TypeScript-Fehler während des Build
Ursache: Fehlende Typdefinitionen.
Lösung: Option 1: Installieren Sie Cloudflare Workers Typen:
npm install --save-dev @cloudflare/workers-typesOption 2: Verwenden Sie stattdessen die JavaScript-Version (benennen Sie in [[path]].js um)
CORS-Fehler in der Konsole
Ursache: CORS-Header werden nicht korrekt hinzugefügt.
Lösung: Stellen Sie sicher, dass Ihre Funktion beide Punkte enthält:
- Der OPTIONS-Handler für Preflight-Anfragen
responseHeaders.set('Access-Control-Allow-Origin', '*')in der Antwort
Geolokalisierung ist falsch
Ursache: Client-IP wird nicht weitergeleitet.
Lösung: Überprüfen Sie, dass Ihre Funktion folgendes enthält:
const clientIP = request.headers.get('CF-Connecting-IP') || ''
proxyHeaders.set('X-Zenovay-Real-IP', clientIP)
Script wird geladen, aber keine Daten im Dashboard
Ursache: Tracking-Code Mismatch.
Lösung:
- Öffnen Sie DevTools Konsole (F12 → Console Tab) und suchen Sie nach Fehlern
- Überprüfen Sie, dass Ihr
data-tracking-codeexakt mit dem in Ihrem Zenovay Dashboard übereinstimmt (case-sensitive!) - Stellen Sie sicher, dass die Domain in Zenovay registriert ist
Nächste Schritte
- Custom Events - Verfolgung von Benutzerinteraktionen
- Visitor Identification - Link Analytics zu Benutzern
- Troubleshooting - Mehr Hilfe bei Problemen