# Custom checkout

> For checkouts you build yourself (Stripe Elements, Paddle, Chargebee, Braintree or anything else) — check the disclosure text and the rendered page, then use Checkbox Elements or the generated HTML.

When the pay button is on your own page, the disclosure and consent are your code. Checkbox checks the text and the
rendered page before you deploy, and gives you engine-verified replacement copy and HTML.

## Check the disclosure text {#disclosure}

Describe what is next to your pay button: the text, where it sits, how it looks, and the consent checkbox if there is
one. Checkbox models the page and runs the ten sign-up checks:

```curl
curl https://app.checkbox.site/v1/checks/disclosure \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Start your free trial today!",
    "merchant_name": "Joybox",
    "price": 19.99,
    "interval": "month",
    "trial_days": 14,
    "cancel_url": "https://joybox.example/account/cancel",
    "placement": { "above_button": true, "font_size_px": 12 },
    "consent": { "checkbox": true, "prechecked": true }
  }'
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const result = await checkbox.checks.disclosure({
  text: 'Start your free trial today!',
  merchant_name: 'Joybox',
  price: 19.99,
  interval: 'month',
  trial_days: 14,
  cancel_url: 'https://joybox.example/account/cancel',
  placement: { above_button: true, font_size_px: 12 },
  consent: { checkbox: true, prechecked: true },
});
console.log(result.verdict);
console.log(result.replacement.disclosure_text);
console.log(result.replacement.consent_label);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

result = checkbox.checks.disclosure(
    text="Start your free trial today!",
    merchant_name="Joybox",
    price=19.99,
    interval="month",
    trial_days=14,
    cancel_url="https://joybox.example/account/cancel",
    placement={"above_button": True, "font_size_px": 12},
    consent={"checkbox": True, "prechecked": True},
)
print(result["verdict"])
print(result["replacement"]["disclosure_text"])
print(result["replacement"]["consent_label"])
```

This one fails several checks (no renewal terms, a pre-checked box, small text). `replacement` holds the verified
wording, the consent label and `html` you can paste. With the CLI:

```bash
checkbox check disclosure --text "Start your free trial today!" --merchant-name Joybox \
  --price 19.99 --interval month --trial-days 14 --cancel-url https://joybox.example/account/cancel \
  --consent-checkbox --prechecked --offline
```

## Check the rendered page {#page}

Before you deploy, send the HTML of the page as the browser renders it (after JavaScript). The static check reads
buttons, terms blocks, consent checkboxes and links; layout is estimated, so a passing layout estimate is reported as
`needs_review` until a scan confirms it:

```bash
cat > checkout.html <<'EOF'
<form action="/subscribe" method="post">
  <p>Joybox Pro — $19.99/month</p>
  <button type="submit">Subscribe</button>
</form>
EOF
checkbox check page --file checkout.html --merchant-name Joybox --price 19.99 --interval month --offline
```

## Use Elements {#elements}

The simplest fix is [Checkbox Elements](https://checkbox.site/docs/elements): the `<checkbox-disclosure>` element renders the locked
disclosure for your terms directly above your pay button, keeps the button disabled until the box is ticked, repairs
its own styling if your CSS breaks the requirements, and records each consent as evidence.

## Verify after deploying {#verify}

Register the site with `checkout_url` set to the page with the pay button (and `checkout_steps` when the shopper has to
click through first), then run `checkbox verify --wait` or [`verifySite`](https://checkbox.site/docs/api/compliance-plans#verifySite). The
synthetic shopper visits from each state on desktop and mobile and measures the real layout.
