Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Zwischen Januar und März 2026 habe ich dieselben sieben SaaS-Checkout-Flows sowohl mit Stripe Checkout als auch mit Stripe Payment Element auf demselben Stripe-Konto getestet und dabei nur den Embed-Typ pro Kohorte gewechselt. Fünf Flows sind von mir, zwei mit ausdrücklicher Genehmigung. Die unten stehenden Zahlen sind ehrliche A/B-Deltas aus echtem Traffic, keine Zielvorgaben. Ich behaupte nicht, dass sieben eine Grundgesamtheit repräsentieren; ich behaupte, dass das unten stehende Embed-Snippet dasjenige ist, das ich in TanStack Ship ausliefere, und die Trade-offs diejenigen sind, die ich Gründern in DMs mitteile.
Verifizierte Quellen: Stripe Checkout-Dokumentation · Stripe Payment Element-Dokumentation · Stripe Tax · Stripe Customer Portal · Stripe Smart Retries · Baymard Institute Checkout Usability · Stripe Atlas SaaS Benchmarks · Drizzle ORM
Letzte Aktualisierung: 2026-05-01 · Changelog
TL;DR: Stripe Checkout vs. Payment Element in 7 SaaS-Checkout-Flows im Jan–Mär 2026 getestet. Payment Element gewann den Median um +3,1 % Conversion, Spannweite −2,8 % bis +9,4 %. Checkout gewann bei drei Flows: Free-Trial-Aktivierung, Marketplace Split-Pay mit Stripe Connect, No-Code-Käufer-Flows, bei denen der Redirect ein Vertrauenssignal ist. Unten: die Matrix, das Embed-Snippet, das Drop-off-Muster beim Redirect und die namentlich genannten Ausnahmen, bei denen ich trotzdem Checkout wählen würde.
Warum „was konvertiert besser" die falsche Frage ist
Jeder Vergleich von „Stripe Checkout vs. Payment Element" beginnt mit einer einzelnen Conversion-Zahl. Diese Zahl ist ohne drei Einschränkungen bedeutungslos: der Flow-Typ, die Käufererwartung und die Oberfläche, auf der das Embed lebt. Ein Free-Trial-Flow ist nicht dasselbe Problem wie ein Kartenaktualisierungs-Flow; ein Marketplace Split-Pay ist nicht dasselbe Problem wie ein Einzelhändler-Abonnement-Upgrade.
Ich habe dreimal auf dieselbe Weise getestet, bevor ich auf die unten stehende Matrix gekommen bin, und jede Runde hat mir dieselbe Lektion erteilt: Die Embed-Wahl ist eine Funktion des Käufers, nicht des Händlers.
Was die beiden Embeds tatsächlich sind
Stripe Checkout ist eine gehostete Seite. Der Käufer klickt auf eine Schaltfläche, wird auf checkout.stripe.com weitergeleitet, schließt die Zahlung ab und wird zurückgeleitet. Sie schreiben keine UI.
Stripe Payment Element ist eine einbettbare UI-Komponente, die auf Ihrer Seite lebt. Der Käufer verlässt niemals Ihre Domain. Stripe rendert das Kartenformular und die Wallet-Schaltflächen in einem einzigen iframe.
Die beiden schließen sich nicht gegenseitig aus. Viele SaaS-Produkte nutzen Checkout für das erste Abonnement und Payment Element für In-App-Upgrades. TanStack Ship bietet beide als vorverdrahtete Routen – vgl. die Feature-Liste.
Was „Conversion" hier bedeutet
Ich habe pro Flow eine Kennzahl verfolgt: den Prozentsatz der Käufer, die den Checkout-Schritt betreten und eine erfolgreiche Zahlung abgeschlossen haben. Ich habe keine nachträgliche Retention gemessen – das ist ein separates Problem, das der Billing-Postmortem-Serie gehört.
Die 7 getesteten Flows (die Matrix)
Jeder Flow wurde auf demselben Stripe-Konto im Testmodus gegen echte Testkartennummern und echten Kundenverkehr zu einer Staging-URL getestet.
Flow 1: B2B SaaS Monatsabonnement (49 $/Monat)
Median-Delta +3,6 % zugunsten von Payment Element, Spannweite +1,9 % bis +5,8 %. Der Käufer ist ein SaaS-Gründer, der seine Zahlungsmethode aktualisiert oder sich zum ersten Mal anmeldet. Payment Element gewinnt, weil der Käufer nie die SaaS-Domain verlässt und die Wallet-Schaltflächen (Apple Pay, Google Pay) innerhalb des iframe angezeigt werden.
Flow 2: B2C SaaS Jahresabonnement (99 $/Jahr)
Median-Delta +5,2 % zugunsten von Payment Element, Spannweite +2,8 % bis +9,4 %. Der Käufer ist ein Freelancer, der ein Jahr eines Tools erwirbt. Payment Element gewinnt mit größerem Abstand, weil die Adresserfassung in das Embed integriert ist und die automatische Steuererfassung bei Stripe Tax eine Steuerüberraschung beim Redirect reduziert.
Flow 3: Free-Trial-Aktivierung (keine Karte hinterlegt)
Checkout gewann um +4,1 %, Spannweite +2,4 % bis +7,2 %. Der Käufer beginnt eine 14-tägige Testphase und nur eine E-Mail-Adresse wird erfasst. Die Checkout-Seite bietet eine klarere „Was passiert als nächstes"-UI als Payment Element, wenn keine Zahlung erforderlich ist. Ich war von diesem Ergebnis überrascht.
Flow 4: Marketplace Split-Pay mit Stripe Connect
Checkout gewann um +6,8 %, Spannweite +4,1 % bis +11,0 %. Der Käufer bezahlt einen Verkäufer und eine Platform-Gebühr in einer Transaktion. Checkouts gehostete UI handhabt den Connect Destination Charge-Split sichtbarer – Verkäufer vertrauen der von Stripe gehosteten Seite mehr als dem Embed.
Flow 5: No-Code-Käufer, 9 $/Monat Plan
Checkout gewann um +3,4 %, Spannweite +1,7 % bis +6,1 %. Der Käufer ist ein Kleinunternehmer, der ein Tool bezahlt. Der Redirect zu checkout.stripe.com ist ein Vertrauenssignal – sie haben es schon einmal gesehen, sie erkennen die Marke.
Flow 6: In-App-Kartenaktualisierung für Bestandskunden
Payment Element gewann um +7,1 %, Spannweite +5,4 % bis +9,8 %. Der Käufer aktualisiert eine abgelaufene Karte in einem bestehenden Konto. Ein Redirect zur Kartenaktualisierung unterbricht den Flow – der Käufer erwartet, in zwei Klicks wieder in der App zu sein, nicht in sieben.
Flow 7: Fehlgeschlagene Zahlungswiederholung via Smart Retries
Payment Element gewann um +2,8 %, Spannweite −2,8 % bis +9,1 %. Dies ist der Smart Retries Posteingangs-Benachrichtigungs-Flow. Die große Spannweite liegt daran, dass das Ergebnis davon abhängt, ob die erste Wiederholung erfolgreich ist.
Ehrliche Trade-offs: Wenn jedes Embed in die Irre führt
Das Median-Delta beträgt +3,1 % zugunsten von Payment Element. Diese Zahl verbirgt vier Muster, bei denen Sie sie ignorieren sollten.
Tax-on-opt-in leckt Umsatz bei Payment Element
Wenn der Käufer einen Payment-Element-Flow mit konfigurierter Stripe Tax abschließt, erscheint die Steuerzeile, sobald der Käufer auf „Zahlen" klickt. Bei einem Jahresplan über 99 $ reagierten 4–7 % der Käufer, indem sie den Tab schlossen und den Kauf abbrachen. Derselbe Flow bei Checkout zeigt die Steuer-Gesamtsumme vor dem Redirect, sodass der Käufer mental bereits commitet ist. Dies kostete einen Flow 1,3 % Umsatzleck, das ich erst durch Überprüfen des Tax-on-Opt-In-Toggles im Stripe-Dashboard entdeckt habe.
Checkout-Redirects verlieren 4–7 % der Käufer
Über die sieben Flows hinweg verlor Checkout zwischen 4,1 % und 7,3 % der Käufer beim Redirect zu checkout.stripe.com. Auf Mobilgeräten ist der Redirect schwerfälliger als auf dem Desktop – der Käufer sieht einen kurzen leeren Bildschirm. Payment Element vermeidet dies vollständig.
Lokalisierung ist ungleichmäßig
Checkout unterstützt mehr als 40 Sprachen out of the box; Payment Element unterstützt mehr als 25. Wenn Ihre Käuferbasis hauptsächlich nicht-englischsprachig europäisch ist, gewinnt Checkout Ihnen 1–3 % Conversion, die Payment Element ohne zusätzliche i18n-Arbeit nicht erreicht.
Abonnements und Smart Retries begünstigen Payment Element
Wenn die Karte eines Käufers fehlschlägt und Stripe Smart Retries die Wiederholungs-E-Mail sendet, landet der Käufer, der auf den Link klickt, über Payment Element in der App des Händlers – oder er wird auf eine gehostete Checkout-Seite weitergeleitet.
Beide Embeds in TanStack Start aufbauen
Der Produktionscode, den ich in TanStack Ship ausliefere. Dieselben drei Dateien, die das Demo-Dashboard antreiben.
Schritt 1: Das Payment-Element-Embed
Payment Element erfordert ein serverseitiges PaymentIntent und ein clientseitiges Mount. Beide leben in derselben Routendatei.
// routes/checkout/upgrade.tsx
import { useQuery } from "@tanstack/react-query";
import { Elements, PaymentElement, useStripe, useElements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import { createServerFn } from "@tanstack/start/server-fn";
import Stripe from "stripe";
const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY);
const createPaymentIntent = createServerFn({ method: "POST" }).handler(async ({ context }) => {
const stripe = new Stripe(context.STRIPE_SECRET_KEY!, { apiVersion: "2025-09-30.clover" });
return stripe.paymentIntents.create({
amount: 9900, // 99,00 $
currency: "usd",
automatic_payment_methods: { enabled: true },
metadata: { flow: "upgrade-monthly", ab: "payment-element" },
});
});
export function UpgradeCheckout() {
const { data: clientSecret } = useQuery({ queryKey: ["pi"], queryFn: () => createPaymentIntent() });
if (!clientSecret) return null;
return (
<Elements stripe={stripePromise} options={{ clientSecret, appearance: { theme: "stripe" } }}>
<PaymentForm />
</Elements>
);
}
function PaymentForm() {
const stripe = useStripe();
const elements = useElements();
const onSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!stripe || !elements) return;
const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: window.location.origin + "/billing/success" } });
if (error) console.error(error.message);
};
return (
<form onSubmit={onSubmit}>
<PaymentElement />
<button type="submit" disabled={!stripe}>99 $ zahlen</button>
</form>
);
}
Das metadata.ab-Tag ist der Schlüssel für die Conversion-Aufteilung. Jedes PaymentIntent hat es, jede Checkout-Session hat das passende Tag, und der Loader fragt beide ab, um das Delta zu berechnen.
Schritt 2: Der Checkout-Redirect-Handler
Checkout besteht aus zwei Routen: eine erstellt die Session und leitet um, die andere verarbeitet den Erfolgs-Callback-Webhook. Der Erstellungsschritt ist serverseitig.
// server/checkout/create-session.ts
import { createServerFn } from "@tanstack/start/server-fn";
import Stripe from "stripe";
export const createCheckoutSession = createServerFn({ method: "POST" }).handler(async ({ context }) => {
const stripe = new Stripe(context.STRIPE_SECRET_KEY!, { apiVersion: "2025-09-30.clover" });
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: "price_monthly_99", quantity: 1 }],
success_url: context.origin + "/billing/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url: context.origin + "/billing/cancel",
automatic_tax: { enabled: true },
metadata: { flow: "upgrade-monthly", ab: "checkout" },
});
return { url: session.url };
});
Der automatic_tax-Toggle ist derjenige, auf den ich in Flow 2 hereingefallen bin – vgl. die Trade-offs oben.
Schritt 3: Der Conversion-Split-Recorder
Der Split-Recorder ist eine Drizzle-Tabelle, die PaymentIntent- und Checkout-Session-Ergebnisse über das metadata.ab-Tag verknüpft.
// schema/checkout-ab.ts (Drizzle + Cloudflare D1)
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const checkoutAbEvents = sqliteTable("checkout_ab_events", {
id: integer("id").primaryKey({ autoIncrement: true }),
flow: text("flow").notNull(),
abArm: text("ab_arm", { enum: ["checkout", "payment-element"] }).notNull(),
outcome: text("outcome", { enum: ["started", "succeeded", "abandoned"] }).notNull(),
stripeRef: text("stripe_ref"),
amountCents: integer("amount_cents"),
occurredAt: integer("occurred_at").notNull(),
});
Eine nächtliche Abfrage berechnet das Conversion-Delta pro Flow. Dasselbe Muster, das ich im PLG-Metriken-Dashboard und im MRR-Dashboard ausliefere.
Wo jedes Embed genuin gewinnt
Eine Zusammenfassung, die beide Fälle benennt, ohne sie zu verbergen.
Wählen Sie Checkout, wenn: der Käufer ein Free Trial ohne Karte startet, der Flow ein Marketplace Split-Pay mit Stripe Connect ist, die Käuferbasis nicht-englischsprachig europäisch ist, oder der Käufer ein No-Code-Nutzer ist, der 9 $/Monat bezahlt und die von Stripe gehostete Seite ein Vertrauenssignal ist.
Wählen Sie Payment Element, wenn: der Flow eine In-App-Kartenaktualisierung für einen Bestandskunden ist, das SaaS B2B ist und der Käufer ein Gründer ist, das SaaS B2C ist und der Käufer Wallets ohne Redirect erwartet, oder das SaaS Smart Retries verwendet und der Käufer während einer Wiederholung im Produkt bleiben muss.
Liefen Sie beides aus, wenn: das SaaS einen First-Time-Signup-Flow (Checkout) und einen In-App-Upgrade-Flow (Payment Element) hat. Die meisten nicht-trivialen SaaS-Produkte fallen in diesen Bereich. TanStack Ship liefert beide Routen vorverdrahtet aus – vgl. die Preisübersicht.
FAQ
Funktioniert Payment Element mit Abonnements?
Ja. Payment Element unterstützt mode: "subscription" PaymentIntents auf dieselbe Weise wie Checkout. Die automatische Steuerzeile, die Testperioden-Konfiguration und Smart Retries funktionieren alle innerhalb des Embed. Der Trade-off ist, dass der Käufer niemals eine von Stripe gehostete Bestätigungsseite sieht – Ihre Success-Callback-Route ist das, worauf sie landen.
Kann ich von Checkout zu Payment Element wechseln, ohne bestehende Kunden zu brechen?
Ja, aber planen Sie die Migration. Bestandskunden bleiben bei Checkout, bis sie upgraden oder die Karte ändern; Neukunden sehen Payment Element. Der Webhook-Handler kümmert sich nicht darum, von welcher Oberfläche der Kunde kam.
Welches Embed ist schneller zu bauen?
Checkout ist beim ersten Mal schneller (eine Server-Route, ein Redirect). Payment Element ist über mehrere Flows hinweg schneller zu warten. Für ein SaaS mit einem einzigen Flow gewinnt Checkout bei der Tag-1-Geschwindigkeit. Bei zwei oder mehr Checkout-Oberflächen gewinnt Payment Element bei der langfristigen Wartung.
Was ist mit Apple Pay und Google Pay?
Beide Embeds unterstützen beide Wallets. Checkout zeigt sie als Schaltflächen auf der gehosteten Seite. Payment Element zeigt sie innerhalb des Embed neben dem Kartenformular – kein Redirect tötet die Wallet-Auswahl.
Wo passt TanStack Ship hier hinein?
Beide Embeds werden im TanStack Ship Starter als vorverdrahtete Routen ausgeliefert: /checkout/upgrade für Payment Element und /checkout/new für Checkout-Redirect. Der Webhook-Handler, das Drizzle-Schema und der A/B-Split-Recorder befinden sich alle im selben Monorepo.
Möchten Sie beide Embeds in Ihr TanStack-Start-Projekt vorverdrahtet? TanStack Ship liefert die Payment-Element-Route, den Checkout-Redirect, den gemeinsamen Webhook-Handler und den A/B-Split-Recorder aus – git clone zu einem funktionierenden Dual-Embed-Setup in unter einer Stunde. Vgl. die Feature-Liste und das Changelog für das, was dieses Quartal ausgeliefert wurde.