03 · Revenue
Link Stripe Checkout sales to their visits
Two small changes where your server creates the session: the visitor's id in metadata, and the session's id on your success page.
01Pass the visitor's id in metadata
Where your server creates the Checkout Session, read the _tally_vid cookie and pass it as tally_visitor_id in metadata. For a subscription, pass it in subscription_data.metadata too, so its renewals follow the first payment. In payment mode, leave subscription_data out: Stripe takes it only for subscriptions.
// Express with cookie-parser (app.use(require('cookie-parser')())), where you create
// the Checkout Session; stripe = require('stripe')(process.env.STRIPE_SECRET_KEY).
app.post('/checkout', async (req, res) => {
const visitorId = req.cookies['_tally_vid'];
const metadata = visitorId ? { 'tally_visitor_id': visitorId } : {};
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_123', quantity: 1 }],
success_url: 'https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}',
metadata,
// Renewals read the subscription's metadata. In payment mode, leave this line out.
subscription_data: { metadata },
});
res.redirect(303, session.url);
});
// app/api/checkout/route.ts
import { cookies } from 'next/headers';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST() {
const visitorId = (await cookies()).get('_tally_vid')?.value;
const metadata: Record<string, string> = visitorId ? { 'tally_visitor_id': visitorId } : {};
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_123', quantity: 1 }],
success_url: 'https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}',
metadata,
// Renewals read the subscription's metadata. In payment mode, leave this line out.
subscription_data: { metadata },
});
return Response.json({ url: session.url });
}
# Flask, where you create the Checkout Session (stripe.api_key is your secret key).
import stripe
from flask import redirect, request
@app.post("/checkout")
def checkout():
visitor_id = request.cookies.get("_tally_vid")
metadata = {"tally_visitor_id": visitor_id} if visitor_id else {}
session = stripe.checkout.Session.create(
mode="subscription",
line_items=[{"price": "price_123", "quantity": 1}],
success_url="https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}",
metadata=metadata,
# Renewals read the subscription's metadata. In payment mode, leave this line out.
subscription_data={"metadata": metadata},
)
return redirect(session.url, code=303)
# Rails: app/controllers/checkouts_controller.rb (Stripe.api_key is your secret key).
class CheckoutsController < ApplicationController
def create
visitor_id = cookies['_tally_vid']
metadata = visitor_id ? { 'tally_visitor_id' => visitor_id } : {}
session = Stripe::Checkout::Session.create(
mode: 'subscription',
line_items: [{ price: 'price_123', quantity: 1 }],
success_url: 'https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}',
metadata: metadata,
# Renewals read the subscription's metadata. In payment mode, leave this line out.
subscription_data: { metadata: metadata }
)
redirect_to session.url, allow_other_host: true, status: :see_other
end
end
<?php
// Where you create the Checkout Session (stripe/stripe-php).
$stripe = new \Stripe\StripeClient(getenv('STRIPE_SECRET_KEY'));
$visitorId = $_COOKIE['_tally_vid'] ?? null;
$metadata = $visitorId ? ['tally_visitor_id' => $visitorId] : [];
$session = $stripe->checkout->sessions->create([
'mode' => 'subscription',
'line_items' => [['price' => 'price_123', 'quantity' => 1]],
'success_url' => 'https://example.com/thanks?session_id={CHECKOUT_SESSION_ID}',
'metadata' => $metadata,
// Renewals read the subscription's metadata. In payment mode, leave this line out.
'subscription_data' => ['metadata' => $metadata],
]);
header('Location: ' . $session->url, true, 303);
02Keep the session's id on your success page
Add ?session_id={CHECKOUT_SESSION_ID} to success_url (to return_url for embedded Checkout), with your own page's address. Stripe fills in the session's id, and the snippet on that page reports it, so the payment is linked even when the cookie couldn't be read. A checkout_session_id parameter works too.
https://yoursite.com/thanks?session_id={CHECKOUT_SESSION_ID}04Check it worked
Something missing, or not what you see? Write to support@tallybyoutpost.com and say which page.