Toss for Craft CMS

Configuration

Settings

Settings → Plugins → Toss.

SettingWhat it does
Policy URI formatWhere published policies live. Must contain {slug}.
Recompile automaticallyRebuilds every policy when the questionnaire changes. Publishing stays deliberate either way.
Warn when a policy goes out of dateCompares what is published with what would be generated now.
Place kit markup automaticallyInjects kits into every front-end page. Off means you place them in Twig.
Skip these pathsOne per line, * allowed. Kit markup is not injected into a matching URI.
Consent cookie name / lifetimeThe first-party cookie the consent token lives in.
Honour Global Privacy ControlTreats Sec-GPC: 1 as an opt-out of the marketing category.
Log consent decisionsStores each decision so you can show consent was given.
Record a hash of the IP addressHashed with your security key — never the address itself.
Retention periodsDays to keep consent and acceptance records. 0 keeps them forever.

Acceptance retention defaults to forever on purpose. An acceptance record exists to be produced years later, and a schedule that quietly deletes it defeats the reason for collecting it.

The questionnaire

About seventy typed questions in fourteen groups. Two behaviours are worth knowing:

Questions that stop applying are blanked, not merely hidden. Turning off do you sell physical goods clears the shipping answers, so a stale shipping address cannot be picked up later by a clause whose own condition happens to be true.

Legal regimes are derived, not asked about. Nobody knows off-hand whether the CPRA covers them, and everybody knows whether they sell to Californians. Toss works out which of CalOPPA, CCPA/CPRA, the state privacy laws, COPPA, GDPR, PIPEDA, CAN-SPAM, DMCA §512 and the FTC endorsement guides apply, and shows you the list.

Multi-site

The global answer set is your business. A site row holds only the keys that differ — a translated site is the same company, and making somebody retype the address for it guarantees one copy is eventually wrong.

A blank value in a site override falls back to the global answer. It does not erase it.

Use the scope switch at the top of the questionnaire to edit one site's overrides.

The script inventory

Toss → Scripts is what makes the cookie policy true and what consent gates. Fourteen presets ship with the plugin, each carrying the right category, the cookies it sets, and the vendor's privacy policy:

Google Analytics 4, Google Tag Manager, Google Ads, Meta Pixel, LinkedIn Insight, TikTok Pixel, Hotjar, Microsoft Clarity, Plausible, Fathom, YouTube embeds, Intercom, Stripe.js, reCAPTCHA.

Add your own with a category, a placement and the markup to inject.

A tag pasted into a template appears in neither the cookie policy nor the consent gate. The audit says so out loud rather than leaving it to be discovered.

Categories

necessary runs immediately and cannot be switched off. preferences, analytics and marketing wait for consent. A preset filed in the wrong category is the one bug in a consent system that matters, so each one ships with its category already decided.

Three presets are necessary on purpose: Plausible and Fathom set no cookies and collect no personal data, and Stripe.js is part of taking a payment — a checkout that will not load is not a privacy win. All three still appear in the generated cookie table.

Clause overrides

Open a policy and you get one panel per clause. Leave it alone and the wording improves when the library does. Override it and your wording survives updates. Required clauses can be reworded but not removed.

{{ dotted.key }} interpolates an answer. [[ … ]] is an optional run that vanishes whole if anything inside it is empty — which is how you write "and call us on [[{{ contact.phone }}]]" without publishing a dangling sentence.

Permissions

Six of them, and publishing is separate from editing. Editing a legal text and being the person who signs it off are different jobs in most organisations that have both.