Features

Cross-cutting capabilities shared across widgets. Each section sets a global default in FuWidget.init() that individual widgets can override via data attributes.

Lead Collection

Lead collection follows a hierarchy of configurations, allowing both global and content-specific settings.

🚧

Important:

Lead collection must be enabled in the Management Portal (Auth Requirement = "LEAD") for any lead collection configuration to take effect.

Configuration Hierarchy

  1. Management Portal Configuration
    • Set under Configuration → Auth Requirement
    • Enables/disables lead collection for specific content
    • Options: "FREE", "LEAD", "REGISTERED"
  2. Global Widget Configuration
    • Set during widget initialization
    • Applies to all content unless overridden
  3. HTML Attribute Configuration
    • Set per widget instance
    • Overrides global configuration

Example Configuration

  1. Enable leads in Management Portal:
Configuration -> Auth Requirement -> LEAD
  1. Global configuration in widget initialization:
FuWidget.init({
	// ... other config
	leads: {
		defaultFields: ["fullName", "email"], // Default fields for all widgets
		position: "after", // Default position
		campaignId: "default-campaign", // Default campaign ID
		campaignName: "Default Campaign", // Default campaign name
		syncWithProfile: false, // Default profile synchronization setting
	},
});
  1. Individual widget configuration:
<div
    data-component="fu-widget"
    data-content-type="classic-quiz"
    data-content-id="quiz-123"
    data-lead-fields="firstName,lastName,email"  // Overrides defaultFields
    data-lead-position="before"                  // Overrides position
    data-campaign-id="summer-campaign"           // Overrides campaignId
    data-campaign-name="Summer Campaign 2024"    // Overrides campaignName
    data-lead-sync-with-profile="true"           // Overrides syncWithProfile (default: false)
></div>

Available Lead Fields

  • fullName — Full name input
  • firstName — First name input
  • lastName — Last name input
  • email — Email input
  • gender — Gender selection
  • country — Country selection
  • phoneCountryCode — Phone country code
  • phoneNumber — Phone number input

Lead Form Position

  • before — Lead form appears before content
  • after — Lead form appears after content

Profile Synchronization

The data-lead-sync-with-profile attribute controls whether anonymous user profiles are synchronized with the database after successful lead form submission. This feature is essential for displaying user names in leaderboards, tracking user participation across widgets, and enabling data export capabilities.

Supported Widgets:

  • Classic Quiz
  • Personality Quiz
  • Match Quiz
  • Poll
  • Collect Lead

Configuration Options

  • "true" — Enable profile synchronization
  • "false" — Disable profile synchronization (default)

Global Configuration

FuWidget.init({
	// ... other config
	leads: {
		// ... other lead config
		syncWithProfile: true, // Enable profile sync by default for all widgets
	},
});

Per-Widget Configuration

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="quiz-123"
	data-lead-sync-with-profile="true"
></div>

Use Cases

Enable when:

  • You want to display user nicknames or names in leaderboards across multiple widgets
  • You plan to export user data for marketing campaigns
  • You need to analyze user behavior across different content types

Disable when:

  • You only need basic lead collection without user tracking
  • Privacy regulations require minimal data retention
  • You want to reduce database storage requirements
  • You're collecting leads for one-time campaigns only

Technical Details

When profile synchronization is enabled:

  • Anonymous user profiles are linked to the submitted lead information
  • User participation data is preserved across widget interactions
  • Export functionality can access complete user participation history

When profile synchronization is disabled:

  • Lead information is collected but not linked to user profiles
  • Each widget interaction is treated independently
  • Export functionality is limited to basic lead information
📘

See Widgets → Collect Lead for a standalone lead form with custom fields and consents.


Sign-in & Additional CTA

The sign-in call-to-action (CTA) feature lets you customise the label and click behavior for authentication prompts in widgets that require user sign-in. This is particularly useful for Classic Quiz, Poll, and Either/Or widgets where users need to authenticate to participate.

The system automatically detects when a user is authenticated by fetching their profile using sdk.profile.getOwn().getInfo() and checking the anonymous property. Anonymous users are considered not authenticated and will see the sign-in CTA when required.

Configuration Hierarchy

The sign-in CTA configuration follows this priority order (highest to lowest):

  1. Data attributes — Widget-specific overrides
  2. Main config — Global defaults
  3. Translated defaults — Localized fallback values based on widget type
  4. Built-in defaults — Final fallback values

Global Configuration

FuWidget.init({
	// ... other config
	signInCTA: {
		defaultLabel: "Sign in to participate",
		onClick: () => {
			// Your custom sign-in logic
			window.location.href = "/signin";
			// Or show a modal
			// showSignInModal();
			// Or trigger your authentication system
			// authService.showLogin();
		},
	},
});

Per-Widget Configuration

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="your-quiz-id"
	data-signin-cta-label="Join Now to Vote!"
	data-signin-cta-onclick="showCustomSignInModal()"
></div>

Configuration Options

signInCTA Object Properties

PropertyTypeRequiredDescription
defaultLabelstringNoThe text displayed on the sign-in button. If not provided, uses translated text based on widget type ("Sign in to play" for games, "Sign in to vote" for polls)
onClickfunctionNoFunction to execute when the sign-in button is clicked
urlstringNoDirect URL for the CTA link. Can be used instead of or in addition to onClick
targetstringNoLink target for the URL. Options: _self, _blank. Default: _self

additionalCTA Object Properties

The additionalCTA follows the same structure as signInCTA and can be used to add a secondary call-to-action button in widgets.

PropertyTypeRequiredDescription
defaultLabelstringNoThe text displayed on the additional CTA button
onClickfunctionNoFunction to execute when the additional CTA button is clicked
urlstringNoDirect URL for the CTA link. Can be used instead of or in addition to onClick
targetstringNoLink target for the URL. Options: _self, _blank. Default: _self

Data Attributes

Sign-in CTA:

AttributeDescriptionExample
data-signin-cta-labelOverride the button label for this widget"Join Now!"
data-signin-cta-onclickJavaScript code to execute on click"window.open('/signin', '_blank')"
data-signin-cta-urlDirect URL for the CTA link"https://yourdomain.com/signin"
data-signin-cta-targetLink target (_self, _blank, etc.)"_blank"

Additional CTA:

AttributeDescriptionExample
data-additional-cta-labelOverride the button label for this widget"Learn More"
data-additional-cta-onclickJavaScript code to execute on click"console.log('clicked')"
data-additional-cta-urlDirect URL for the CTA link"https://yourdomain.com/info"
data-additional-cta-targetLink target (_self, _blank)"_blank"

Authentication Detection

The widget system automatically determines user authentication status by:

  1. Fetching User Profile: Uses sdk.profile.getOwn().getInfo() when the SDK is available
  2. Checking Anonymous Status: Examines the anonymous property in the profile response
  3. Setting Authentication State: Users with anonymous: false are considered authenticated
  4. Reactive Updates: Authentication status is checked once and made available to all widgets

Use Cases

Redirect to Sign-in Page

signInCTA: {
	defaultLabel: "Sign In",
	url: '/login',
	target: '_self'
}

Or using onClick:

signInCTA: {
	defaultLabel: "Sign In",
	onClick: () => {
		window.location.href = '/login';
	}
}

Show Modal Dialog

signInCTA: {
	defaultLabel: "Login to Continue",
	onClick: () => {
		document.getElementById('signin-modal').style.display = 'block';
	}
}

Open Sign-in in New Tab

signInCTA: {
	defaultLabel: "Sign In",
	url: '/signin',
	target: '_blank'
}

Or using onClick:

signInCTA: {
	defaultLabel: "Sign In",
	onClick: () => {
		window.open('/signin', '_blank');
	}
}

Trigger Third-party Authentication

signInCTA: {
	defaultLabel: "Login with SSO",
	onClick: () => {
		// Trigger your authentication provider
		authProvider.login();
	}
}

Using Additional CTA

You can add a secondary call-to-action button alongside the sign-in CTA:

FuWidget.init({
	// ... other config
	signInCTA: {
		defaultLabel: "Sign In",
		url: '/signin',
		target: '_self'
	},
	additionalCTA: {
		defaultLabel: "Learn More",
		url: '/about',
		target: '_blank'
	}
});

Or configure it per widget using data attributes:

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="your-quiz-id"
	data-additional-cta-label="View Rules"
	data-additional-cta-url="/rules"
	data-additional-cta-target="_blank"
></div>
📘

NOTE: Additional CTA is only supported in Classic Quiz, Poll, Personality Quiz and Match Quiz widgets.

Security Considerations

  • The data-signin-cta-onclick attribute executes JavaScript code, so ensure you trust the source.
  • Validate and sanitize any user-provided onclick code in production environments.
  • Consider using CSP (Content Security Policy) headers to restrict inline script execution.

Rules Display

The Rules Display feature controls how game rules are presented to users. You can choose between a modal dialog (default) or a link to an external page.

Supported Widgets

  • Classic Quiz Widget
  • Poll Widget
  • Personality Quiz Widget
  • Match Quiz Widget
  • Event Game Widget

Display Types

Modal Display (Default)

When type is set to "modal" or not specified, rules are displayed in a modal dialog. The modal shows the rules content from the backend (if available).

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "modal" // This is the default behavior
	}
});

Link Display

When type is set to "link", a link is displayed instead of a modal. Useful when you want to direct users to a dedicated rules page.

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "link",
		url: "/game-rules",
		target: "_blank" // Opens in new tab
	}
});

Global Configuration

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "link", // "modal" or "link"
		url: "https://example.com/rules", // Required when type is "link"
		target: "_blank" // Optional: "_blank", "_self", "_parent", "_top"
	}
});

Per-Widget Configuration

Modal Display (Per Widget)

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="your-quiz-id"
	data-rules-display-type="modal"
></div>

Link Display (Per Widget)

<div
	data-component="fu-widget"
	data-content-type="poll"
	data-content-id="your-poll-id"
	data-rules-display-type="link"
	data-rules-display-url="https://example.com/poll-rules"
	data-rules-display-target="_blank"
></div>

Configuration Options

rulesDisplay Object Properties

PropertyTypeRequiredDefaultDescription
type"modal" | "link"No"modal"Display type: modal dialog or external link
urlstringYes*-URL to open when type is "link" (*Required only for link type)
target"_blank" | "_self" | "_parent" | "_top"No-Link target attribute (only used when type is "link")

Data Attributes

AttributeTypeDescription
data-rules-display-type"modal" | "link"Display type for this specific widget
data-rules-display-urlstringURL to open when type is "link"
data-rules-display-target"_blank" | "_self" | "_parent" | "_top"Link target attribute

Configuration Priority

The configuration follows this priority order (highest to lowest):

  1. Data attributes — Widget-specific overrides
  2. Main config — Global defaults
  3. Component defaults — Built-in fallback (modal display)

Usage Examples

Example 1: Global Modal Display

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "modal"
	}
});

All widgets will display rules in a modal dialog.

Example 2: Global Link Display

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "link",
		url: "https://example.com/general-rules",
		target: "_blank"
	}
});

All widgets will display a link to the rules page that opens in a new tab.

Example 3: Mixed Configuration

FuWidget.init({
	// ... other config
	rulesDisplay: {
		type: "link",
		url: "https://example.com/general-rules",
		target: "_blank"
	}
});
<!-- This quiz uses the global link configuration -->
<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="quiz-1"
></div>

<!-- This poll overrides to use modal display -->
<div
	data-component="fu-widget"
	data-content-type="poll"
	data-content-id="poll-1"
	data-rules-display-type="modal"
></div>

<!-- This quiz overrides with a different rules URL -->
<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="quiz-2"
	data-rules-display-type="link"
	data-rules-display-url="https://example.com/special-quiz-rules"
	data-rules-display-target="_self"
></div>

Best Practices

  1. Use Modal for Short Rules: If your rules are brief and can be displayed inline, use the modal display type for better user experience.
  2. Use Link for Detailed Rules: If you have comprehensive rules or legal terms, use the link display type to direct users to a dedicated page.
  3. Consistent Target Behavior: When using link type, be consistent with the target attribute across your widgets. Use "_blank" to open in a new tab (recommended for external links) or "_self" to open in the same window.
  4. Per-Widget Customization: Use data attributes to customize rules display for specific widgets that need different behavior from the global configuration.

Authentication Requirements

Widgets support different authentication requirements that can be configured in the Management Portal.

Authentication Requirement Types

RequirementDescriptionSign-in CTA Behavior
null (None)No authentication requiredNever shown
"FREE"Just for fun, without authNever shown
"LEAD"Lead collection requiredNot shown (handled by lead collection)
"REGISTERED"User registration requiredShown to anonymous users

Supported Widgets

The following widgets support authentication requirements and will show the sign-in CTA when needed:

  • Classic Quiz Widget: Shows sign-in CTA instead of "Start Quiz" button (uses backend authRequirement)
  • Personality Quiz Widget: Shows sign-in CTA instead of "Start Quiz" button (uses backend authRequirement)
  • Either-Or Widget: Shows sign-in CTA instead of "Start" button (uses backend authRequirement)
  • Poll Widget: Shows sign-in CTA instead of voting options (uses backend authRequirement)
  • Player of the Match Widget: Shows sign-in CTA instead of vote buttons (uses configurable authRequirement)

Configuration

Authentication requirements are configured in the Management Portal for each piece of content. When set to "REGISTERED", the widget will:

  1. Check if the user is authenticated (not anonymous)
  2. Show the appropriate interface based on authentication status
  3. Allow authenticated users to participate immediately
  4. Prompt unauthenticated users to sign in first
📘

See Getting Started → Authentication for how the widget connects to the API.


Theming

There are two theming systems. themeOptions is the modern, comprehensive system and themes almost every widget. theme is a legacy property that now only styles a handful of not-yet-migrated widgets.

📘

In short:

Use themeOptions by default. Only set the legacy theme if you embed Match Prediction, Team Next Match Prediction, Player of the Match, or List — those four are the only widgets it still affects. The legacy theme is being phased out as the remaining widgets migrate to themeOptions.

Which system themes which widget?

Theming systemWidgets it controls
themeOptions (recommended)Classic Quiz · Personality Quiz · Poll · Either/Or · Match Quiz · Event Game · Pick The Pair · Chance Game · Collect Lead · Leaderboard · Discussion · Predictor · Betslip
theme (legacy)Match Prediction · Team Next Match Prediction · Player of the Match · List

The themeOptions widgets are rendered from the component library and read their styling only from themeOptions — they ignore theme.primaryColor, and their light/dark mode comes from themeOptions.mode. The four legacy widgets are styled by the theme object instead (see below).

Legacy Theme Configuration

The legacy theme object has two fields, both still in effect — but only for the four widgets listed above (Match Prediction, Team Next Match Prediction, Player of the Match, List):

  • theme.primaryColor — sets the primary color palette (light + dark) for those widgets.
  • theme.mode — sets their default light/dark color scheme.
theme: {
    mode: "light", // "light" or "dark"
    primaryColor: {
        50: "#ebfff3",
        100: "#d1ffe4",
        200: "#a3ffc8",
        300: "#66f59d",
        400: "#2ce97a",
        500: "#0cd664",
        600: "#09b954",
        700: "#078f42",
        800: "#056b31",
        900: "#034d23",
    }
}
🚧

Deprecated direction:

Setting theme has no effect on the 13 themeOptions widgets. As the four legacy widgets migrate to the component library, theme will be removed entirely in favor of themeOptions.

Advanced Theme Configuration with themeOptions

This is the recommended, comprehensive theming system, used by all 13 component-library widgets (Classic Quiz, Personality Quiz, Poll, Either/Or, Match Quiz, Event Game, Pick The Pair, Chance Game, Collect Lead, Leaderboard, Discussion, Predictor, and Betslip):

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

// Default theme options
const themeOptions: CustomThemeOptions = {
  mode: "light", // or 'dark'
  colorSchemes: {
    light: {
      palette: {
        success: {
          plainColor: "#4CAF50",
          outlinedBorder: "#4CAF50",
        },
        danger: {
          softBg: "#FEE4E2",
          plainColor: "#F44336",
          outlinedBorder: "#F44336",
        },
        primary: {
          plainColor: "#1A77D2",
          outlinedBorder: "#1A77D2",
          onPrimary: "#FAFAFA",
          primaryContainer: "#2397F3",
        },
        warning: {
          softBg: "#FEF0C7",
          plainColor: "#DC6803",
        },
      },
      textPrimary: "#212121",
      textSecondary: "#212121",
      textColor: "#212121",
      textDisabled: "#212121",
      surface: "#FFFFFF",
      onSurface: "#F5F5F5",
      surfaceVariant: "#EEEEEE",
      surfaceTintDim: "#212121",
      surfaceInverse: "#F5F5F5",
      outlineEnabledBorder: "#E0E0E0",
      secondaryContainer: "#BDBDBD",
    },
    dark: {
      palette: {
        primary: {
          plainColor: "#1A77D2",
          outlinedBorder: "#1A77D2",
          onPrimary: "#FAFAFA",
          primaryContainer: "#2397F3",
        },
        success: {
          plainColor: "#4CAF50",
          outlinedBorder: "#4CAF50",
        },
        danger: {
          softBg: "#430A0A",
          plainColor: "#F44336",
          outlinedBorder: "#F44336",
        },
        warning: {
          softBg: "#FEF0C7",
          plainColor: "#DC6803",
        },
      },
      textPrimary: "#FAFAFA",
      textSecondary: "#FAFAFA",
      textColor: "#FAFAFA",
      textDisabled: "#FAFAFA",
      surface: "#424242",
      onSurface: "#212121",
      surfaceVariant: "#616161",
      surfaceTintDim: "#FAFAFA",
      surfaceInverse: "#FAFAFA",
      outlineEnabledBorder: "#757575",
      secondaryContainer: "#757575",
    },
  },
  customBreakpoints: {
    values: {
      xs: 0,
      sm: 444,
      md: 600,
      lg: 900,
      xl: 1200,
      xxl: 1536,
    },
  },
  spacingScale: {
    "3xs": "2px",
    "2xs": "4px",
    xs: "8px",
    sm: "12px",
    md: "16px",
    lg: "24px",
    xl: "32px",
    "2xl": "40px",
    "3xl": "48px",
  },
  customFontFamily: {
    light: {
      primary: "Ubuntu, sans-serif",
      secondary: "Roboto, sans-serif",
    },
    dark: {
      primary: "Ubuntu, sans-serif",
      secondary: "Roboto, sans-serif",
    },
  },
  customRadius: {
    light: {
      none: "0px",
      "2xs": "2px",
      xs: "4px",
      sm: "8px",
      md: "12px",
      lg: "16px",
      xl: "24px",
      "2xl": "232px",
      full: "1000px",
    },
    dark: {
      none: "0px",
      "2xs": "2px",
      xs: "4px",
      sm: "8px",
      md: "12px",
      lg: "16px",
      xl: "24px",
      "2xl": "232px",
      full: "1000px",
    },
  },
  border: {
    light: {
      size: "1px",
    },
    dark: {
      size: "2px",
    },
  },
  imageBackgroundGradient: {
    light: {
      standard:
        "linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, rgba(18, 18, 18, 0.8) 100%)",
      split:
        "linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, rgba(18, 18, 18, 0.8) 100%)",
    },
    dark: {
      standard:
        "linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, rgba(18, 18, 18, 0.8) 100%)",
      split:
        "linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, rgba(18, 18, 18, 0.8) 100%)",
      overlay:
        "linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, rgba(18, 18, 18, 0.8) 100%)",
    },
  },
};

FuWidget.init({
    // ... other config
    themeOptions: themeOptions,
});

Content Labels

Custom labels can be set for each content piece from the Management Portal under the Labels configuration.

Prize Labels

  • prizeCardTitle — Title of the prize card
  • prizeCardDescription — Description in the prize card
  • prizeCta — Call to action for prize details

Lead Form Labels

  • leadTitle — Title of the lead form
  • leadDescription — Description text for lead collection
  • leadCta — Submit button text
  • leadSuccessTitle — Success message title
  • leadSuccessDescription — Success message description

Score Message Labels

  • scoreMessagePerfect — Override the default message when a user gets a perfect score.
  • scoreMessageAmazing — Override the default message when a user gets 80+%.
  • scoreMessageWellDone — Override the default message when a user gets 60+%.
  • scoreMessageGoodEffort — Override the default message when a user gets 40+%.
  • scoreMessageKeepGoing — Override the default message when a user gets less than 40%.

Localization

The widget supports multiple languages for both the UI and content, set independently:

  • language — Controls the widget UI language
  • fansUnited.lang — Controls the content language from the Fans United API
FuWidget.init({
	language: "en",          // UI language
	fansUnited: {
		lang: "en",          // Content language
		// ... other config
	},
});

Available UI Languages (language)

  • bg — Bulgarian
  • en — English
  • ro — Romanian
  • pt — Portuguese
  • sr — Serbian
  • fr — French
  • de — German
  • it — Italian
  • fr-be — Belgian French
  • pl — Polish
  • pt-br — Brazilian Portuguese
  • el — Greek

Available Content Languages (fansUnited.lang)

  • bg — Bulgarian
  • en — English
  • ro — Romanian
  • el — Greek
  • sk — Slovak
  • pt — Portuguese
  • sr — Serbian
  • hu — Hungarian
  • sv — Swedish
  • es — Spanish
  • fr — French
  • nl — Dutch
  • de — German
  • it — Italian

All-Widget Language Support

The FU Widget system supports multiple languages for all widget types. Each widget displays content in the language specified in the configuration. All widgets support the following languages:

  • English (en)
  • Bulgarian (bg)
  • Romanian (ro)
  • Portuguese (pt)
  • Serbian (sr)
  • French (fr)
  • German (de)
  • Italian (it)
  • Belgian French (fr-be)
  • Polish (pl)
  • Brazilian Portuguese (pt-br)
  • Greek (el)

Options Layout

The optionsLayout configuration controls how answer options are displayed in widgets that support multiple choice answers (Classic Quiz, Personality Quiz, Poll, Event Game).

Available Layout Options

  • twoByTwo — Displays answer options in a 2x2 grid layout (2 columns). Best for widgets with 4 or fewer options.
  • row — Displays answer options in a single row (horizontal layout). Best for 2–3 short options.
  • column — Displays answer options in a single column (vertical layout, one per row). Best for longer option text or many options.

Global Configuration

Set the default layout for all widgets:

FuWidget.init({
	// ... other config
	optionsLayout: "column", // or "twoByTwo" or "row"
});

Per-Widget Configuration

Override the global setting for individual widgets:

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="your-quiz-id"
	data-options-layout="twoByTwo"
></div>

Supported Widgets

The following widgets support the optionsLayout configuration:

  • Classic Quiz
  • Personality Quiz
  • Poll
  • Event Game

Display Configuration

The widget supports the following display configuration options:

FuWidget.init({
	// ... other config
	displayPlayNextSection: true, // Show/hide "Play Next" section (default: true)
	displayQuizDescription: true, // Show/hide quiz description (default: true)
	defaultImagePlaceholderUrl: "https://example.com/placeholder.jpg", // Default placeholder image URL
});
  • displayPlayNextSection — Controls the visibility of the "Play Next" section in quiz widgets (default: true)
  • displayQuizDescription — Controls the visibility of quiz descriptions (default: true)
  • defaultImagePlaceholderUrl — An optional URL for the default placeholder image used when content images fail to load or are not available

These options can also be set on individual widget instances:

<div
	data-component="fu-widget"
	data-content-type="classic-quiz"
	data-content-id="quiz-123"
	data-display-play-next-section="false"
	data-display-quiz-description="false"
	data-default-image-placeholder-url="https://example.com/custom-placeholder.jpg"
></div>

URL Configuration

The widget supports configuring URLs for different content types. These URLs are used when a user clicks an item in a List widget.

FuWidget.init({
	// ... other config
	urls: {
		classicQuizUrl: "/quiz/{CONTENT_ID}",
		personalityQuizUrl: "/personality-quiz/{CONTENT_ID}",
		eitherOrUrl: "/either-or/{CONTENT_ID}",
		pollUrl: "/poll/{CONTENT_ID}",
		matchQuizUrl: "/match-quiz/{CONTENT_ID}",
	},
});

URL Pattern Keys

  • urls.classicQuizUrl — URL pattern for quiz content
  • urls.personalityQuizUrl — URL pattern for personality quiz content
  • urls.eitherOrUrl — URL pattern for either/or games
  • urls.pollUrl — URL pattern for polls
  • urls.matchQuizUrl — URL pattern for match quiz games

Each URL pattern should include the {CONTENT_ID} placeholder, which is replaced with the actual content ID when generating links.

📘

The same patterns can be set under the list config key, and overridden per-widget on the List widget with data-*-url attributes. See Widgets → List.


SPA Refresh

For Single Page Applications (SPAs) or dynamic content scenarios where widgets need to be reinitialized after navigation or content changes, use the refresh method:

// Manually refresh all widgets on the page
FuWidget.refresh();

When to Use Widget Refresh

  • SPA Navigation: After navigating to a new page that contains widgets
  • Dynamic Content Loading: When new widget elements are added to the DOM via JavaScript
  • Content Updates: When widget content IDs or configurations change dynamically
  • Error Recovery: To reinitialize widgets after network errors or other issues

Implementation Example

// Example for SPA router
router.on("route-changed", () => {
	// Small delay to ensure DOM is updated
	setTimeout(() => {
		FuWidget.refresh();
	}, 100);
});

// Example for dynamic content loading
function loadNewContent() {
	fetch("/api/content")
		.then((response) => response.text())
		.then((html) => {
			document.getElementById("content").innerHTML = html;
			// Refresh widgets after new content is loaded
			FuWidget.refresh();
		});
}

Important Notes

  • The refresh method will reinitialize ALL widgets on the page.
  • Existing widget state will be lost during refresh.
  • Only call refresh when necessary to avoid performance issues.
  • Widgets automatically prevent double initialization, so calling refresh multiple times is safe.