UserChoice
UserChoice runs conjoint analysis directly on your site so you can measure which product trade-offs users prefer.
How It Works
UserChoice presents a series of product configurations ("concepts") and asks respondents to choose among them. Across tasks, this reveals which attributes and combinations drive preference.
For a deeper methodology overview, see the conjoint analysis guide.
When to Use UserChoice
Embed UserChoice where users can evaluate product options:
- Product roadmap pages — Let users vote on feature combinations
- Feature request pages — Understand which options people actually prefer
- Upcoming features sections — Validate concepts before building
- Beta and early-access pages — Gather preference data from engaged users
Installation
CDN (Recommended)
<!-- Modern browsers (ES modules) -->
<script type="module" src="https://unpkg.com/@sensefolks/userchoice/dist/sf-userchoice/sf-userchoice.esm.js"></script>
<!-- Legacy browsers -->
<script nomodule src="https://unpkg.com/@sensefolks/userchoice/dist/sf-userchoice/sf-userchoice.js"></script> NPM
npm install @sensefolks/userchoice Framework Integration
HTML
<sf-userchoice
survey-key="your-survey-uuid"
completion-message="Thank you for your feedback!">
</sf-userchoice> React
import '@sensefolks/userchoice';
function App() {
return (
<sf-userchoice
survey-key="your-survey-uuid"
completion-message="Thank you!">
</sf-userchoice>
);
} Vue
<template>
<sf-userchoice
survey-key="your-survey-uuid"
completion-message="Thank you!">
</sf-userchoice>
</template>
<script>
import '@sensefolks/userchoice';
export default {name: 'App'};
</script> Angular
// app.module.ts
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import '@sensefolks/userchoice';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}) For Next.js and Svelte examples, see the Embedding Tutorial.
API Reference
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
surveyKey | survey-key | string | — | Required. UUID of the survey from your dashboard |
completionMessage | completion-message | string | 'Thank you for your response!' | Message shown after submission |
Events
This component does not emit custom DOM events.
CSS Custom Properties
Override these custom properties to theme the component:
| Property | Default | Description |
|---|---|---|
--sf-primary | #005fcc | Primary accent color |
--sf-primary-hover | #0047a3 | Primary color hover state |
--sf-text-primary | #111827 | Primary text color |
--sf-text-secondary | #6b7280 | Secondary/muted text color |
--sf-error-color | #dc2626 | Error state color |
--sf-card-bg | #ffffff | Card/container background |
--sf-card-border | #d1d5db | Card/container border color |
--sf-card-radius | 8px | Card/container border radius |
--sf-button-radius | 6px | Button border radius |
--sf-transition | 150ms ease | Default transition timing |
--sf-selected-bg | #e8f0fe | Selected card background |
--sf-selected-border | #005fcc | Selected card border color |
--sf-card-shadow | 0 1px 3px rgba(0,0,0,0.1) | Card shadow |
--sf-card-shadow-hover | 0 4px 12px rgba(0,0,0,0.15) | Card hover shadow |
--sf-none-bg | #f9fafb | "None" option background |
--sf-none-border | #9ca3af | "None" option border |
--sf-error-bg | #fef2f2 | Error state background |
--sf-error-border | #fca5a5 | Error state border |
--sf-progress-bg | #e5e7eb | Progress bar track background |
--sf-progress-fill | #005fcc | Progress bar fill color |
/* Override theme tokens on the component */
sf-userchoice {
--sf-primary: #7c3aed;
--sf-primary-hover: #6d28d9;
--sf-card-radius: 12px;
--sf-button-radius: 8px;
--sf-selected-bg: #ede9fe;
--sf-selected-border: #7c3aed;
} CSS Parts
Style individual elements inside the shadow DOM using ::part(). UserChoice has a large number of parts because of its multi-step,
card-based UI:
/* Survey container */
sf-userchoice::part(survey-container) { }
/* Steps */
sf-userchoice::part(step) { }
sf-userchoice::part(choice-task-step) { }
sf-userchoice::part(respondent-details-step) { }
sf-userchoice::part(completion-step) { }
/* Headings */
sf-userchoice::part(heading) { }
sf-userchoice::part(task-heading) { }
sf-userchoice::part(respondent-details-heading) { }
sf-userchoice::part(completion-heading) { }
/* Task header & progress */
sf-userchoice::part(task-header) { }
sf-userchoice::part(task-instructions) { }
sf-userchoice::part(progress-indicator) { }
sf-userchoice::part(progress-bar) { }
sf-userchoice::part(progress-fill) { }
sf-userchoice::part(progress-text) { }
/* Concepts */
sf-userchoice::part(concepts-container) { }
sf-userchoice::part(concept) { }
sf-userchoice::part(concept-selected) { }
sf-userchoice::part(concept-unselected) { }
sf-userchoice::part(none-option) { }
sf-userchoice::part(concept-header) { }
sf-userchoice::part(concept-radio) { }
sf-userchoice::part(concept-title) { }
sf-userchoice::part(concept-attributes) { }
sf-userchoice::part(concept-attribute) { }
sf-userchoice::part(attribute-label) { }
sf-userchoice::part(attribute-value) { }
/* Buttons */
sf-userchoice::part(button-container) { }
sf-userchoice::part(button) { }
sf-userchoice::part(back-button) { }
sf-userchoice::part(next-button) { }
sf-userchoice::part(submit-button) { }
sf-userchoice::part(retry-button) { }
/* Respondent details form */
sf-userchoice::part(form-container) { }
sf-userchoice::part(form-field) { }
sf-userchoice::part(form-label) { }
sf-userchoice::part(form-input) { }
sf-userchoice::part(form-select) { }
sf-userchoice::part(hcaptcha-container) { }
sf-userchoice::part(input) { }
sf-userchoice::part(select) { }
sf-userchoice::part(required-indicator) { }
sf-userchoice::part(radio-group) { }
sf-userchoice::part(radio-option) { }
sf-userchoice::part(radio-input) { }
sf-userchoice::part(radio-label) { }
sf-userchoice::part(checkbox-group) { }
sf-userchoice::part(checkbox-option) { }
sf-userchoice::part(checkbox-input) { }
sf-userchoice::part(checkbox-label) { }
/* Completion */
sf-userchoice::part(completion-summary) { }
sf-userchoice::part(summary-text) { }
/* Messages & errors */
sf-userchoice::part(message) { }
sf-userchoice::part(error-message) { }
sf-userchoice::part(loading-message) { }
sf-userchoice::part(error-container) { }
/* Branding */
sf-userchoice::part(branding) { }
sf-userchoice::part(branding-link) { }
sf-userchoice::part(branding-logo) { }
/* Accessibility */
sf-userchoice::part(announcements) { } Accessibility
- Full keyboard navigation (Tab, Arrow keys, Enter/Space)
- ARIA labels and live regions for screen readers
- Progress announcements ("Choice Task 2 of 5")
- Focus indicators and high contrast mode support
- Respects
prefers-reduced-motion
Browser Support
| Browser | Version |
|---|---|
| Chrome | 88+ |
| Firefox | 85+ |
| Safari | 14+ |
| Edge | 88+ |
| IE11 | Supported (ES5 build) |