By the end of this guide, you'll know what Products are, how to create one, how to configure and embed a Checkout button on your website, and how orders, emails, refunds, and the voucher disposition dialog flow afterwards. For voucher-specific workflows (manual issuance, expiry, redemption), see Vouchers.
What you'll need
- Edit access to the website where you'll embed the Checkout button
- A payment gateway in Settings → Payments (Stripe is the supported gateway today) — you can create the product first; the checkout will only go live once a gateway is configured
- ~10 minutes
- One product set up with a price and currency
- A Checkout button live on your website
- The first test order arriving in your admin, with confirmation emails sent to you and the guest
What are Products?
Products are sellable items priced in a single currency. Each Checkout button sells one product at an adjustable quantity, paid online via Stripe. After payment, the order shows up in your admin and both you and the guest receive an email.
Two product types ship today:
- Product — physical or digital item. Standard one-off sale flow.
- Voucher — generates one customer-facing code per unit purchased. Code format is
[PREFIX-]XXXX-XXXX. See Vouchers for voucher-specific behaviour.
Each product runs in one of two pricing modes:
- Single price — one fixed per-unit price. Guest picks a quantity, total = price × quantity. Use this for a flat-rate item (a 1 800 CZK bottle, a 500 CZK voucher).
- Options — multiple lines, each with its own title, optional description, and price. Guest picks a quantity per line (e.g. Adult — 1 000 CZK ×2, Child — 500 CZK ×1) and the total is the sum. Use this for tiered or variant pricing — and for voucher products that sell multiple denominations from one Checkout button.
Step 1: Create your first product
Sidebar → Products → click the + button at the top of the rail. The new-product form opens:
| Field | What it does |
|---|---|
| Name | Appears on the Checkout button, the order list, and in confirmation emails. |
| Type | Product (physical / digital item) or Voucher (printable code — see Vouchers). |
| Country / Currency | Selecting a country auto-fills the currency. Currency must match what your gateway supports. |
| Pricing mode | Single price (one per-unit price) or Options (N lines, each with title / description / price). See "What are Products?" above. |
| Price (single mode) | Per-unit price in major units (e.g. 1890 for 1 890 CZK). |
| Options (options mode) | Add at least one line. Title and description are optional; price is required and at least one option must be > 0. |
| Voucher settings (only if type = Voucher) | Code prefix (1–8 letters/digits, optional) + Validity (days) (empty = unlimited). |
Click Save. You land on the product detail page — a single page with sections for basic info, payments, quantity defaults, notifications, and (for vouchers) issued-code settings.
Payments live in their own section. If no gateway is configured yet, a helper line links you to Settings → Payments — the public checkout aborts with a clear error until one is set, but you can build out the rest of the product first.
Step 2: Configure a Checkout button
A product is just data — guests buy it through a Checkout button. On the product detail page, open Checkouts in the sidebar and click Add checkout.
The checkout detail page has three sections — Identity, Appearance, and Embedding.
Per-checkout settings:
| Setting | What it does |
|---|---|
| Name | Internal admin label so you can tell multiple buttons apart. |
| Language | Overrides the product's default language for this specific button. |
| Button label | Visible text on the button (e.g. Order now, Buy a voucher). |
| Primary color | Hex color for the button and the dialog accent. |
| Mode | Light / dark theme of the embedded dialog. |
| Background | White / black / transparent — match the surrounding page. |
| Size | Small / medium / large button. |
| Embed type | Choose how the snippet renders on your site: Button (pre-styled trigger you drop into your HTML), Script (we render the button inside an iframe), or Iframe (drop our checkout page into a bare iframe). Saved per checkout; the Checkouts list shows which mode each one uses. |
| Custom dialog fields | Use the BookingFieldsEditor to ask for delivery address, gift message, anything else. Same component that powers booking widgets. |
Quantity bounds (min ≤ default ≤ max) are set on the product, not per checkout — one set applies to every Checkout button bound to the product.
Save the checkout. The Embedding section reveals the embed code (two flavours, see next step) and a View public preview link that opens /checkout/{token} in a new tab.
Step 3: Embed the button on your website
Pick an Embed type in the checkout's Embedding section. The snippet on the right updates to match.
Button (recommended) — Pre-styled HTML button with your appearance settings baked in as inline styles. Drop into your site and re-style the inline style attribute as needed. Best for full design control.
<button data-cabintale-checkout="{token}" style="…">Order now</button>
<script src="https://admin.cabintale.com/widget-embed.js" async></script>
Script (advanced) — We render the button for you inside an iframe. Zero styling effort, but you give up CSS control over the trigger.
<cabintale-root data-checkout="{token}"></cabintale-root>
<script src="https://admin.cabintale.com/widget-embed.js" async></script>
Iframe (simple) — Drop the checkout page itself into a bare iframe. Needs the companion widget-dialog.js script on the same page so dialog overlays still work full-viewport.
<iframe src="https://admin.cabintale.com/checkout/{token}" style="border:none; width:100%; min-height:80px"></iframe>
<script src="https://admin.cabintale.com/widget-dialog.js" async></script>
All three open the dialog as a full-viewport overlay via postMessage. Origins are validated; multiple Checkout buttons on the same page don't interfere.
Step 4: How the checkout dialog works for guests
When a guest clicks the button, a 4-step dialog opens:
- Quantity
- Single-price products: one stepper bounded by your product's
min/max. Total updates live. - Options products: one stepper per option line. Total = Σ (option price × line quantity). At least one line must be > 0 to advance.
- Single-price products: one stepper bounded by your product's
- Custom fields — anything you configured via the dialog-fields editor (email, delivery address, gift message). Required fields are validated client- and server-side.
- Review — order summary with per-line totals (for options) and grand total.
- Pay — opens Stripe Checkout in the widget's language. After payment, Stripe redirects back and the dialog confirms with Order received.
For voucher products, step 4 lists the generated code(s) on the success step. Codes also go out in the guest email — see the next step.
Step 5: Receiving orders
Orders land in Products → {product} → Orders with status paid. The Orders list shares its visual rhythm with Bookings — name + price + date + reference chip + status pill — so flipping between order types feels consistent.
- The order detail shows quantity, line total, payment status, guest details, and every custom field the guest filled in.
- The Payments table shows the Stripe transaction(s) (one row per attempt). Refund icons appear on succeeded rows.
- The Issued vouchers panel (voucher orders only) lists every generated code with status + expiry + per-row cancel.
- The owner email lands in your inbox as
NewOrderNotificationMail— a heads-up that money came in. - The guest email is
OrderConfirmationMail— a receipt with the product name, line items (for options-mode orders), total, custom fields, and (for vouchers) the issued codes rendered as dashed-border chips with code + value + optional expiry.
Both emails go out in the language captured on the order (widget_language is snapshotted at order time, so renaming the product or switching the checkout language later doesn't rewrite history).
Step 6: Send a payment link manually
If a guest's payment failed or they want to pay outside the embedded button (in a chat / email / phone call), generate a pay link from the order detail:
- Open the order's Payments section.
- Click Send payment link. cabintale creates a pending Stripe Checkout session and copies the URL to your clipboard.
- Paste the URL to the guest. They land on
/pay/{token}and complete the payment. - On success, the order flips to paid and confirmation emails go out as usual.
The link button is hidden when the product has no gateway configured or the order is already fully paid.
Step 7: Refunds + voucher disposition
Refunds work the same as for bookings. From the order detail's Payments table:
- Click the refund button on a Succeeded transaction.
- Enter the amount (full or partial) and click Initiate.
- cabintale emails a 6-digit confirmation code to your admin email — type it into the dialog.
- Stripe processes the refund; a new negative-amount row appears in the Payments table.
When the order has paid vouchers, a follow-up dialog appears: Cancel all vouchers or Keep vouchers.
- Cancel all — every paid voucher on the order flips to
cancelled(holder can't redeem). - Keep — vouchers stay valid; only the order's payment state is updated.
The same dialog appears when you cancel (set status → Cancelled and save) or delete the order. On delete + Keep, vouchers' product_order_id becomes NULL but the codes stay valid for the holder.
See Vouchers for voucher-specific cancel + redemption details.
Manual voucher creation
For voucher products, you can issue codes without taking online payment (gift codes, in-person sale, comps). See Vouchers → "Issue vouchers manually".
Limitations (current)
- No cart / no multi-product checkouts. One button = one product (options inside it count as one order). Multi-product catalogs are planned.
- No stock tracking. Sold-out is a manual toggle — flip the Available select in the product header to hide the button.
- No product images yet — coming with the shared media storage rollout.
- No request-mode flow. Products are payments-only.
Related guides
- Set up your payment gateway — Payment gateways
- Vouchers (issue, manual creation, expiry, redemption) — Vouchers
- Refunds and cancellations (same flow as orders) — Refunds and cancellations
- Custom booking form (same editor used for Checkout fields) — Custom booking form
- Email notifications — Email notifications