Consents

Profile consents are checkboxes whose acceptance is recorded against the user's Fans United profile. Eight components accept them today — Predictor, TopX, ClassicQuizPlay, PollVote, EitherOrPlay, EventGamePlay, MatchQuizPlay and PersonalityQuizPlay — all through the same ConsentDef shape. CollectLead has its own, older LeadConsent shape (id / label); both are accepted wherever consents are read.

ConsentDef

interface ConsentDef {
  consentId: string;
  body: string;
  required?: boolean;
  defaultChecked?: boolean;
  position?: "before" | "after";
}
FieldTypeDefaultDescription
consentIdstringConsent identifier. Sent as-is to the Profile API and used to detect an already-accepted consent.
bodystringThe checkbox label. Supports HTML and the {{privacyPolicyUrl}} / {{termsAndConditionsUrl}} tokens.
requiredbooleanfalseBlocks the gate's CTA until ticked. An inline error appears if the user tries to continue without it.
defaultCheckedbooleanfalsePre-ticks the checkbox. Ignored for required consents — a required consent must be an explicit action.
position"before" | "after""before"Game widgets only — every *Play / PollVote component. Where the checkbox is shown; it is per consent, so one array can drive both surfaces. Ignored when a lead form is the gate — see below.

URL tokens

{{privacyPolicyUrl}} and {{termsAndConditionsUrl}} are replaced with links to the entity's own branding URLs — branding.urls.privacyPolicyUrl and branding.urls.termsAndConditionsUrl, configured on the entity in the back office. The link text comes from the widget language (Privacy Policy / Terms and Conditions), or from labels.privacyPolicyUrlLabel / labels.termsAndConditionsUrlLabel where a component exposes them.

If a token has no URL behind it, the link text is rendered as plain text and a warning is logged — the consent is never hidden because of a missing URL.

const consents: ConsentDef[] = [
  {
    consentId: "terms",
    body: "I accept the {{privacyPolicyUrl}} and the {{termsAndConditionsUrl}}",
    required: true,
  },
  {
    consentId: "marketing",
    body: "Send me news and offers by email",
    defaultChecked: true,
  },
];

Game widget surfaces

The game widgets take consents: { items, labels? } and render each consent exactly once, on the surface that owns it. The table below uses the quiz's wording; the others behave the same, with their own action in place of the participation — a vote, a prediction or a game:

Quiz configurationConsent surface
authRequirement: "LEAD" + leads.position: "before"The lead form shown before the questions — all consents, position ignored
authRequirement: "LEAD" + leads.position: "after"The lead form shown after the last answer — all consents, position ignored
No lead formposition: "before" → the start screen; position: "after" → its own step before the participation is submitted

The leads configuration wins because the lead form is already the quiz's gate — adding a second gate screen next to it would ask the user to click through twice.

Where the "before" gate lives differs slightly per widget, because each reuses a screen it already has:

Component"before" surface"after" surface
ClassicQuizPlayThe start screen, forced to appear for every quiz typeIts own step before the participation submit
PersonalityQuizPlayA gate screen before the questionsIts own step before the participation submit
PollVoteA gate screen before the pollIts own step before the vote
MatchQuizPlayA gate screen before the prediction UIIts own step before the prediction
EventGamePlayA gate screen before the prediction UIIts own step before the prediction
EitherOrPlayThe tutorial screen, whose Start button records themIts own step before the results

Every gate keeps its template's participation layout, and its CTA defaults to that widget's own button label.

Without a lead form:

  • "before" — the start screen is shown for every quiz type, including the ones that previously dropped the user straight into question 1. The consents sit above the Start button; the ticked ones are recorded when the user starts.
  • "after" — pressing Finish stops the timer, then a consent step appears before the participation is submitted. Because the timer is already stopped, reading the consents never inflates a timed quiz's score, and a countdown quiz cannot auto-submit behind the step.

Labels

interface ConsentsLabels {
  title?: string;
  description?: string;
  ctaLabel?: string;
  requiredError?: string;
}

One set, used by both standalone surfaces — the start screen and the consent step. Each field falls back to the widget language: the start screen's button defaults to the game's start label, and the consent step's to its finish label, since that step is what submits the participation. ctaLabel overrides whichever button is shown; requiredError is the message shown when the user tries to continue with a required consent unticked. Inside a lead form only requiredError applies, since the form supplies its own title and description.

How many checkboxes appear

Branding URLs are link targets, not checkboxes. The only checkbox they produce on their own is the lead form's built-in agreement line — "I agree to the Privacy Policy and the Terms and Conditions" — and that appears only when no consents are configured:

SurfaceBranding URLs, no consentsBranding URLs + N consents
Lead form1 built-in agreement checkboxN checkboxes — the built-in one is replaced
Start screen / consent stepnoneN checkboxes

To keep an agreement gate while collecting other consents, express it as a required consent whose body uses the URL tokens. That is also the stronger option: a configured consent is recorded through the Profile API, while the built-in checkbox is not stored anywhere.

Already-accepted consents

Accepted consents are loaded once when the widget mounts and filtered out, so a returning user is never asked twice. If that lookup fails, nothing is filtered and the consents are shown — the widget errs toward asking again rather than silently skipping a consent.

A failed consent submission is logged and swallowed: the user still plays and the participation is still submitted.

Related

  • Lead Collection — the lead form that absorbs a quiz's consents.
  • CollectLead — standalone lead form with its own consents prop.

Did this page help you?