When and Why to Use
Use this to identify the most and least preferred items from a set. It's ideal for:
- Prioritizing features, messages, or concepts
- Understanding tradeoffs in preferences
- Reducing scale bias compared to traditional rating questions
Supports full MaxDiff logic with dynamic sets, randomization, and chat and traditional display styles.
Chat Experience
- The question is first shown as an introductory message, then respondents answer one choice question per label per set (e.g. "Least" then "Most")
- The item selected for the first label is disabled for the second
randomize=Truerandomizes item order within each setrandomize_labels=Trueindependently randomizes the order in which the two labels are asked- Without
randomize_labels, labels are asked in the order supplied
Traditional Experience
- Each set is shown once with both labels side by side (e.g. "Select Least and Most")
- Item and label-row randomization are controlled independently
- Ideal for desktop or larger screen interactions
| Chat experience | Traditional experience | Traditional experience on mobile |
|---|---|---|
![]() | ![]() | ![]() |
Configuration Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| question | string | yes | - | Prompt shown above the MaxDiff sets |
| items | List[str] or List[List[str]] | yes | - | Flat list (auto-generated sets) or custom list of sets |
| labels | List[str] | yes | - | Exactly two labels for the selection ends (e.g. ["Least", "Most"]) |
| image | MediaItem | no | - | Optional image shown above the sets |
| randomize | bool | no | False | Randomize item order within each set |
| randomize_labels | bool | no | False | Independently randomize the displayed order of the two labels |
| custom_validator | Callable[[dict[str, str] | str], str | None] | no | - | Called with the parsed set (traditional) or each parsed label choice (chat); return an error message to reject the response, otherwise None |
| dont_know_option | str | no | - | Optionally adds a fixed "Don't know" choice to each task |
| image_label_field | str | no | - | Label field to use for media items in the options |
| show_image_label | bool | no | True | Whether to show image labels for media options |
| image_size | Tuple[int, int] | no | 600x600 | Bounding box size for media options; if omitted, images render at 600x600 |
| number_seconds | int | no | 0 | Seconds to wait before allowing the respondent to continue |
tags | s.tag() | no | - | Used for substitution and grouping in reporting |
| id | str | None | no | None | Optional stable identifier for this question |
Example Code
Simple list with auto-generated sets:
car_brands = ["Ford", "Toyota", "Honda", "Tesla", "BMW", "Audi"]
s.max_diff_question(
"Which of the following car brands do you prefer?",
items=car_brands,
labels=["Least", "Most"]
)
With a fixed "Don't know" option in each task:
s.max_diff_question(
"Which of the following cars do you prefer?",
items=["Ford", "Toyota", "Honda", "Tesla"],
labels=["Least", "Most"],
randomize=True,
randomize_labels=True,
dont_know_option="Don't know"
)
Custom sets and tag substitution:
brand_cars = {
"Ford": [["Focus", "Fiesta", "Mustang"], ["Fusion", "Explorer", "Escape"]],
"Toyota": [["Corolla", "Camry", "Prius"], ["RAV4", "Highlander", "Tacoma"]],
}
for brand in ["Ford", "Toyota"]:
s.max_diff_question(
"Which of the following {brand} cars do you prefer?",
items=brand_cars[brand],
labels=["Least", "Most"],
tags=s.tag(brand=brand)
)
Notes
- If
itemsis a flat list, sets are generated automatically; pass a list of lists to use predefined sets randomizeandrandomize_labelsuse independent randomization, so enabling one does not implicitly reorder the other- In the chat layout, the question is shown as an introductory message and the platform supplies the label-specific follow-up copy — no
{label}placeholder is needed in your question text - Every generated set is asked and reported, but the returned
DictResponsecontains only the two selections from the final set — use the reporting output when you need the selections from every set - Use
custom_validatorfor logic like ensuring diversity across sets or detecting straight-lining




