Classic Quiz Play

ClassicQuizPlay

Interactive quiz component with scoring, three templates, optional answer explanations, lead collection, sign-in gating, and a configurable additional CTA on the results screen.

Import

import { ClassicQuizPlay } from "fansunited-frontend-components";
import { ClassicQuizPlayProps, WidgetTemplate } from "fansunited-frontend-core";

Required props

PropTypeDescription
entityIdstringClassic Quiz identifier (from the Fans United backend).
sdkFansUnitedSDKModelSDK instance.
templateWidgetTemplateLayout — STANDARD, SPLIT, or OVERLAY.
languageLanguageTypeDisplay language.

Optional props

PropTypeDescription
themeOptionsCustomThemeOptionsSee Theming.
showAnswerExplanationsbooleanShow explanations on the results screen.
leadsLeadsOptionsSee Lead Collection.
consentsConsentsConfigProfile consent checkboxes. See Consents and the section below.
imagePosition"left" | "right"STANDARD template only.
defaultImagePlaceholderUrlstringFallback image URL.
userIsLoggedInbooleanPass the host's auth state for sign-in-gated quizzes.
signInCTASignInCTADetailsSee Sign-in CTA. Supports gate, which defers the sign-in ask until the user has played — this is the only component that reads it.
additionalCTAAdditionalCTADetailsSee Additional CTA.
shareCTAShareCTADetailsSee Share CTA.
rulesDisplayRulesDisplaySee Rules Display.
callbacksClassicQuizPlayCallbacksonFinish and onShare — see Callbacks.

Consents

Collect profile consents alongside the participation. The shape is the shared ConsentDef — see Consents for the full field reference, the URL tokens and the checkbox-count rule.

import { ConsentsConfig } from "fansunited-frontend-core";

const consents: ConsentsConfig = {
  items: [
    {
      consentId: "terms",
      body: "I accept the {{privacyPolicyUrl}} and the {{termsAndConditionsUrl}}",
      required: true,
      position: "before",
    },
    {
      consentId: "marketing",
      body: "Send me news and offers by email",
      defaultChecked: true,
      position: "after",
    },
  ],
  labels: {
    title: "Before we save your score",
    ctaLabel: "Continue",
  },
};

<ClassicQuizPlay {...otherProps} consents={consents} />

Where each checkbox appears:

Quiz configurationConsent surface
authRequirement: "LEAD" + leads.position setThe lead form, at the lead's position — all consents, each position ignored
No lead form"before" → the start screen (forced to appear for every quiz type); "after" → its own step before the participation is submitted

The "after" surface is a separate step rather than a checkbox next to the Finish button, so that reading it cannot inflate a timed quiz's score or let a countdown quiz auto-submit behind it. labels applies to both standalone surfaces; inside a lead form only requiredError is used.

Without ctaLabel, the start screen's button keeps the quiz's Start label and the consent step uses its Finish label — the step is what submits the participation. The last question's button then reads "Continue" rather than "Finish", since an "after" consent still has to be shown.

Consents

Collect profile consents alongside the participation. The shape is the shared ConsentDef — see Consents for the full field reference, the URL tokens and the checkbox-count rule.

import { ConsentsConfig } from "fansunited-frontend-core";

const consents: ConsentsConfig = {
  items: [
    {
      consentId: "terms",
      body: "I accept the {{privacyPolicyUrl}} and the {{termsAndConditionsUrl}}",
      required: true,
      position: "before",
    },
    {
      consentId: "marketing",
      body: "Send me news and offers by email",
      defaultChecked: true,
      position: "after",
    },
  ],
  labels: {
    title: "Before we save your score",
    ctaLabel: "Continue",
  },
};

<ClassicQuizPlay {...otherProps} consents={consents} />

Where each checkbox appears:

Quiz configurationConsent surface
authRequirement: "LEAD" + leads.position setThe lead form, at the lead's position — all consents, each position ignored
No lead form"before" → the start screen (forced to appear for every quiz type); "after" → its own step before the participation is submitted

The "after" surface is a separate step rather than a checkbox next to the Finish button, so that reading it cannot inflate a timed quiz's score or let a countdown quiz auto-submit behind it. labels applies to both standalone surfaces; inside a lead form only requiredError is used.

Without ctaLabel, the start screen's button keeps the quiz's Start label and the consent step uses its Finish label — the step is what submits the participation. The last question's button then reads "Continue" rather than "Finish", since an "after" consent still has to be shown.

Answer explanations

Set showAnswerExplanations={true} to reveal per-question explanations on the results screen. The explanations come from the quiz's question configuration on the backend.

<ClassicQuizPlay {...otherProps} showAnswerExplanations={true} />

Examples

Basic

<ClassicQuizPlay
  entityId="quiz-123"
  sdk={sdk}
  template={WidgetTemplate.STANDARD}
  language="en"
/>

Fully customized

<ClassicQuizPlay
  entityId="quiz-123"
  sdk={sdk}
  template={WidgetTemplate.OVERLAY}
  language="en"
  showAnswerExplanations
  userIsLoggedIn={false}
  signInCTA={{
    defaultLabel: "Sign in",
    onClick: openSignIn,
    // Play the first three questions, then ask. Omit `gate` to keep the
    // sign-in screen in front of the whole quiz.
    gate: { position: "step", afterStep: 3 },
  }}
  leads={{
    position: "after",
    fields: ["fullName", "email"],
    campaignId: "quiz-2024",
    campaignName: "Quiz Campaign 2024",
    phoneCountryCode: "44",
    syncWithProfile: true,
  }}
  additionalCTA={{
    defaultLabel: "Learn more",
    url: "https://example.com",
    target: "_blank",
  }}
  rulesDisplay={{ type: "modal" }}
  themeOptions={{ mode: "dark" }}
/>

Did this page help you?