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
| Prop | Type | Description |
|---|---|---|
entityId | string | Classic Quiz identifier (from the Fans United backend). |
sdk | FansUnitedSDKModel | SDK instance. |
template | WidgetTemplate | Layout — STANDARD, SPLIT, or OVERLAY. |
language | LanguageType | Display language. |
Optional props
| Prop | Type | Description |
|---|---|---|
themeOptions | CustomThemeOptions | See Theming. |
showAnswerExplanations | boolean | Show explanations on the results screen. |
leads | LeadsOptions | See Lead Collection. |
consents | ConsentsConfig | Profile consent checkboxes. See Consents and the section below. |
imagePosition | "left" | "right" | STANDARD template only. |
defaultImagePlaceholderUrl | string | Fallback image URL. |
userIsLoggedIn | boolean | Pass the host's auth state for sign-in-gated quizzes. |
signInCTA | SignInCTADetails | See Sign-in CTA. Supports gate, which defers the sign-in ask until the user has played — this is the only component that reads it. |
additionalCTA | AdditionalCTADetails | See Additional CTA. |
shareCTA | ShareCTADetails | See Share CTA. |
rulesDisplay | RulesDisplay | See Rules Display. |
callbacks | ClassicQuizPlayCallbacks | onFinish 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 configuration | Consent surface |
|---|---|
authRequirement: "LEAD" + leads.position set | The 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 configuration | Consent surface |
|---|---|
authRequirement: "LEAD" + leads.position set | The 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" }}
/>Updated 10 days ago
