# Payment pages (/en/docs/platform/features/pci-dss/payment-pages)





Payment pages define what is in PCI DSS scope. Only scripts observed on a page matching an enabled pattern enter the script inventory, so this is the first thing to configure and the thing to get right.

Requires the website **Manager** role.

## Add a pattern [#add-a-pattern]

**PCI DSS** > **Payment pages** > **Add payment page**. Two fields:

* **Name:** A label for the flow, such as `Checkout` or `Card update`.
* **Page URL pattern:** Compared against the full page URL.

```text
https://shop.example.com/checkout*
```

New patterns are created turned on, and you can turn one off afterwards.

Each pattern shows its script and report counts in the Coverage column:

<img alt="The payment pages list, each wildcard pattern showing its script and report counts in the Coverage column, with the last row switched off" src="__img0" width="1237" height="340" />

## Wildcard syntax [#wildcard-syntax]

`*` is the only wildcard. It matches any characters, **including slashes**. Everything else is literal, and the pattern must match the **entire URL**.

| Pattern                               | Matches                                                  | Does not match     |
| ------------------------------------- | -------------------------------------------------------- | ------------------ |
| `https://shop.example.com/checkout*`  | `/checkout`, `/checkout/step-1`, and also `/checkout-v2` | `/cart`            |
| `https://shop.example.com/checkout/*` | everything under `/checkout/`                            | `/checkout` itself |
| `checkout`                            | nothing                                                  | everything         |

That last row surprises people. Because the match is anchored to the whole URL, a bare substring matches nothing. Start from the origin, or lead with `*`.

There is no `?`, no `**`, and no character classes. Patterns are validated when you save, and one that is too complex is rejected, so keep them simple.

You can define up to **100 payment pages per website**.

## What Coverage tells you [#what-coverage-tells-you]

The **Coverage** column shows how many distinct scripts and how many hash reports that pattern has matched, across all stored data rather than a fixed window. Browser-extension scripts are excluded.

Use it as a quick check right after saving. A brand new pattern reading `0 scripts / 0 reports` on a page that definitely gets traffic means the pattern is wrong.

<Callout type="info" title="Coverage counts each pattern independently">
  Coverage is computed per pattern, including disabled ones, so it previews what turning a pattern on would add. Two overlapping patterns both count the same script, and the column does not sum to a website total. The inventory itself deduplicates, so a script matched by several patterns appears once.
</Callout>

## Turn off rather than delete [#turn-off-rather-than-delete]

The **Enabled** switch takes a pattern out of scope immediately and enqueues a rebuild.

Turning every pattern off retires the whole inventory. Retired scripts keep their status, justification, and history, and they come back if you turn the pattern on again, so this is reversible. Deleting a pattern is the same for scripts seen only through it: they leave the inventory on the next rebuild.

Neither action erases evidence. The change ledger is append-only and retired scripts still appear in the evidence pack.

## Overlapping patterns [#overlapping-patterns]

Nothing warns you about overlap, and it is usually harmless. Two things follow from it:

* Coverage numbers double-count, as described in [What Coverage tells you](#what-coverage-tells-you).
* Deleting or turning off one of two overlapping patterns does not retire the shared scripts, because the other pattern still holds them in scope. If you meant to remove something from scope, check every pattern that might match it.

## When a pattern matches nothing [#when-a-pattern-matches-nothing]

No warning appears on the row. If it is your only enabled pattern, the inventory shows an empty state telling you reports are arriving but no reported URL matches.

Compare your pattern against real document URLs from the [CSP hashes](/en/docs/platform/monitoring/script-hash) page. The usual causes are a missing scheme, the wrong host, a `www` mismatch, or forgetting that the match is anchored.

## Next steps [#next-steps]

* [Justification rules](/en/docs/platform/features/pci-dss/justification-rules)
* [Script inventory](/en/docs/platform/features/script-inventory)
* [Reconciliation](/en/docs/platform/features/pci-dss/reconcile)
