Auf Next.js Pages Router installieren
Nutze next/script in pages/_app.tsx. Rohe Script-Tags in _document.tsx laufen an der Skriptoptimierung von Next vorbei. Übergib den Affiliate-Slug vom Client über window.Rekomi.getReferral().
Der Pages Router (das Muster von Next.js aus der Zeit vor dem App Router, das bis Next 16 weiter unterstützt wird) installiert Rekomi über die Komponente next/script in _app.tsx, damit der Loader bei jedem Rendern einer Seite läuft. Füge keine rohen <script>-Tags in _document.tsx ein; sie laden an der Skriptoptimierung von Next vorbei, und du verlierst die Kontrolle über die Ladestrategie. Verkäufe werden außerhalb der Seite erfasst (über deinen Zahlungsanbieter oder einen Server-to-Server-Aufruf), deshalb gibt es kein Convert-Ereignis, das du im Browser auslösen müsstest.
Installation in pages/_app.tsx
Bearbeite pages/_app.tsx und füge die <Script>-Komponente im Return der App-Komponente hinzu:
import type { AppProps } from "next/app";
import Script from "next/script";
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<Script
id="rekomi"
src="https://api.rekomi.com/api/v1/r/loader.js"
strategy="afterInteractive"
data-program-id={process.env.NEXT_PUBLIC_REKOMI_PROGRAM_ID}
data-rkmi-email-capture="auto"
/>
</>
);
}strategy="afterInteractive" verschiebt das Laden auf die Zeit nach der Hydration, und das ist für die Klickerfassung die richtige Balance.
Rekomi erfasst eine E-Mail-Adresse, die ein vermittelter Besucher auf den Seiten, auf denen das Tag läuft, in ein beliebiges E-Mail- oder Textfeld tippt (Registrierung, Login, Checkout und andere Formulare), damit der Verkauf auch dann gutgeschrieben werden kann, wenn dein Checkout keine Empfehlung übergibt. Ohne Empfehlung wird nichts erfasst. Entferne das Attribut data-rkmi-email-capture, um das auszuschalten; explizite Aufrufe von Rekomi.convert() funktionieren weiterhin.
Setze NEXT_PUBLIC_REKOMI_PROGRAM_ID in .env.local (und in den Umgebungsvariablen deines Hostings). Das Präfix NEXT_PUBLIC_ ist nötig, damit die Variable im Browser verfügbar ist.
Warum nicht _document.tsx?
In älteren Next.js-Versionen (vor 14) war _document.tsx ein üblicher Ort für Skripte von Drittanbietern als Inhalt von <Head>. Rohe Script-Tags in _document.tsx laden an der Skriptoptimierung von Next vorbei. Du verlierst die Kontrolle über die Ladestrategie, und bei Upgrades wird das Tag leicht doppelt eingebunden oder geht verloren. Nutze next/script in _app.tsx, das sich in den Lade-Lebenszyklus einfügt. Bleib bei _app.tsx.
Den Verkauf erfassen
Das Browser-Pixel erfasst keine Verkäufe mehr, deshalb gibt es keinen Convert-Aufruf, den du auf einer Erfolgsseite auslösen müsstest. Ein Verkauf wird über einen dieser Wege erfasst:
- Dein Zahlungsanbieter. Verbinde ihn einmal im Schritt Zahlungsanbieter verbinden unter
/dashboard/setup/connect-sales(Stripe, Paddle, Braintree, Shopify, Wix, BigCommerce, Lemon Squeezy, Chargebee, Polar, Recurly, Gumroad, Creem, Dodo Payments oder Mollie), und Verkäufe, Erstattungen und Kündigungen werden automatisch erfasst. - Server-to-Server. Sende den Verkauf aus einer API-Route per POST mit HMAC-Signatur an den S2S-Endpunkt von Rekomi. Siehe Server-zu-Server-Tracking.
- Gutscheincodes. Gib jedem Affiliate einen eigenen Rabattcode (
Kampagne > Gutscheincodes); ein eingelöster Code schreibt ihm den Verkauf im Checkout gut.
Stripe Checkout aus einer App mit Pages Router
Das übliche Muster: Eine API-Route unter pages/api/create-checkout-session.ts erstellt die Stripe-Session serverseitig und leitet den Browser dann zur von Stripe gehosteten URL weiter. Die Rekomi-Empfehlung reist per HTTP-Header vom Browser (wo window.Rekomi.getReferral() sie ausliest) zu deiner API-Route:
// pages/api/create-checkout-session.ts
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") return res.status(405).end();
const referral = req.headers["x-rekomi-referral"] as string | undefined;
const { priceId } = req.body;
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing`,
subscription_data: referral
? { metadata: { rekomi_affiliate_slug: referral } }
: undefined,
});
res.json({ url: session.url });
}Der Code im Browser, der diesen Endpunkt aufruft, liest die Empfehlung mit window.Rekomi.getReferral() aus und leitet sie als Header x-rekomi-referral weiter:
async function startCheckout(priceId: string) {
const referral = window.Rekomi?.getReferral?.();
const res = await fetch("/api/create-checkout-session", {
method: "POST",
headers: {
"Content-Type": "application/json",
...(referral ? { "x-rekomi-referral": referral } : {}),
},
body: JSON.stringify({ priceId }),
});
const { url } = await res.json();
window.location.href = url;
}Leads erfassen (optional)
window.Rekomi.convert() ist jetzt ein Aufruf zur LEAD-Erfassung, kein Verkauf. Auf einer Anmeldeseite kannst du eine Kunden-E-Mail-Adresse vor der Zahlung mit der Empfehlung verknüpfen:
import { useEffect } from "react";
export default function SignupThanks({ email }: { email: string }) {
useEffect(() => {
if (email) window.Rekomi?.ready?.(() => window.Rekomi.convert(email));
}, [email]);
return <div>Thanks for signing up!</div>;
}Die Lead-Erfassung im Browser funktioniert in jedem Plan; der serverseitige Lead-Endpunkt erfordert Starter oder höher. Siehe Leads und Anmeldungen tracken.
Gut zu wissen
next/script gehört in _app.tsx, nicht in _document.tsx. Folge keinen älteren Antworten auf Stack Overflow, die Skripte in <Head> von _document.tsx setzen. Mit diesem Muster verlierst du die Kontrolle über die Ladestrategie von next/script, und bei Upgrades wird das Tag leicht doppelt eingebunden oder geht verloren.
strategy="afterInteractive" ist die richtige Wahl. Wie beim App Router: nach der Hydration laden, aber bevor die Seite untätig wird.
Die Empfehlung gibt es nur im Client. Der Loader schreibt in localStorage, deshalb liest du sie im Browser mit window.Rekomi.getReferral() aus und leitest sie als Header oder Feld im Body weiter. Ein serverseitig lesbares Cookie rekomi_via gibt es nicht, getServerSideProps kann die Empfehlung also nicht aus context.req.cookies lesen; übergib sie wie oben gezeigt vom Client.
Fehlerbehebung
window.Rekomi ist beim Aufruf aus einem Effect undefined. Das Skript ist noch nicht geladen. Nutze window.Rekomi?.ready?.(cb), um zu warten, bis der Loader bereit ist, oder sichere den Aufruf mit if (window.Rekomi) ab.
Die API-Route liefert 500. Die Umgebungsvariable STRIPE_SECRET_KEY fehlt. Setze sie in .env.local und in den Umgebungsvariablen deines Hostings.
Das Script-Tag ist da, aber es wird keine Empfehlung erfasst. Die CSP blockiert, oder der Loader lief auf einer Seite, auf die der Affiliate keine Besucher geschickt hat. Prüfe die Browser-Konsole auf CSP-Verstöße und ob getReferral() auf der Landingpage einen Slug liefert.
rekomi_affiliate_slug fehlt in den Metadaten des Abonnements. Der Header hat keine Empfehlung übertragen. Prüfe, ob der Browser window.Rekomi.getReferral() ausliest und als x-rekomi-referral weiterleitet und ob der Loader auf der Landingpage eine Empfehlung erfasst hat.
Verwandte Seiten
- Tracking-Skript und Referenz zu
window.Rekomi - Server-zu-Server-Tracking: Verkäufe aus deinem Backend erfassen
- Auf Next.js App Router installieren: das moderne Muster; überleg dir einen Umstieg
Auf Next.js App Router installieren
Nutze next/script in app/layout.tsx mit strategy="afterInteractive". Rohe Script-Tags in metadata werden entfernt. Übergib den Affiliate-Slug vom Client über window.Rekomi.getReferral().
Auf React installieren (Vite, CRA, Remix)
Mit Vite und CRA kommt das Script-Tag in index.html, mit Remix und React Router 7 in app/root.tsx. Verkäufe werden über deinen Zahlungsanbieter oder per Server-to-Server erfasst, nicht über einen Convert-Aufruf im Browser.