When and Why to Use
Use this to run a CBC study where each respondent picks one option from a small set of competing product concepts across a sequence of tasks. Ideal for:
- Measuring how attribute levels (brand, price, feature, packaging) drive choice
- Estimating individual-level utility scores via Hierarchical Bayes
- Comparing attribute importance and, with purchase follow-ups, marginal purchase lift
For background on the method, see Choice-Based Conjoint. For the model that produces utility scores and simulated share, see Utility and simulated share methodology.
How Task Sets Work
task_sets is a mapping of task-set id to an ordered list of tasks, where each task is a list of concept ids. Each respondent is assigned one task set using least-fill balancing, which keeps per-task-set exposure roughly even across the fielding. Each task in the assigned set is then presented as a structured comparison with one concept choice.
The simplest way to generate balanced concepts and task sets is the Conjoint Analysis Design Tool, which produces a code block you can paste straight into the survey alongside your screener.
Dict-Backed vs Media-Backed Concepts
Concepts can be defined in two shapes:
- Dict-backed concepts — Python dicts whose
concept_id_tagkey (defaultid) identifies the concept; attributes are displayed as ordered comparison rows.required_tagssets the displayed row order and identifies the fields required on every concept and retained for reporting. - Media-backed concepts —
MediaItemobjects rendered using the same labels, sizing, and media tags as other media-bearing questions. Useimage_label_field,show_image_label, andimage_sizeto configure rendering.
Configuration Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
question | str | yes | - | The question to ask for each conjoint task |
concepts | list[dict] or list[MediaItem] | yes | - | Concept dictionaries or media items to use in tasks |
task_sets | dict[str, list[list[str]]] | yes | - | Mapping of task-set id to tasks, where each task contains concept ids |
concept_id_tag | str | no | 'id' | Tag containing the concept id referenced by task_sets |
required_tags | list[str] or None | no | None | Concept tags to require and report with selected dict-backed concepts |
dont_know_option | str | no | '' | Optional uncertainty choice, separate from explicit none |
randomize | bool | no | False | Randomize option order within each task |
image_label_field | str or None | no | None | Media field to use as the display label for media concepts |
show_image_label | bool | no | True | Whether to show media labels |
image_size | tuple[int, int] or None | no | None | Bounding box size for media options |
number_seconds | int | no | 0 | Seconds to wait before allowing the respondent to continue |
tags | dict[str, Any] or None | no | None | Tags attached to each conjoint task question |
id | str or None | no | None | Optional stable identifier for this question |
none_option | str | no | '' | Completed no-purchase choice beneath the concepts; cannot be combined with anchor_question |
anchor_question | str or None | no | None | Yes/no purchase follow-up after each concept choice; supports {selected.field} piping |
anchor_labels | dict or None | no | None | Display labels with exactly the keys yes and no |
Respondent comparison
On a wide screen, concepts appear side by side with matching attribute rows. The None of these choice sits beneath the concepts when none_option is configured.

On mobile, the concepts stack vertically while retaining each attribute label and the separate None of these choice.

None, Don't Know, and Purchase Follow-ups
Choose the behavior that matches your study:
- Set
none_option="None of these"for an explicit no-purchase alternative beneath the concepts. - Set
anchor_questionto ask whether the respondent would buy the concept they just selected. The platform asks and saves a separate yes/no follow-up after every concept choice. - Use
dont_know_option="Don't know"only for uncertainty. It is separate from a completed no-purchase choice and skips the purchase follow-up.
Explicit none and purchase follow-ups are mutually exclusive. For a purchase follow-up, omit none_option and pass these arguments in your s.conjoint_question(...) call:
anchor_question="Would you buy {selected.brand} for {selected.price}?",
anchor_labels={"yes": "Yes, I would buy it", "no": "No, I would not"},
{selected.price} and other {selected.field} placeholders insert values from the selected concept dictionary or media tags. Every concept must contain the referenced field. Bare {selected} inserts the concept ID. Do not use a Python f-string: the platform substitutes these values when the respondent chooses a concept.
The answer applies to that choice in that task, even if the same concept appears again. Answering No preserves the forced concept choice and records a negative purchase follow-up; it does not turn the response into Don't know.
The follow-up can also use a simple prompt without placeholders, as in this example:

Example Code
Dict-backed concepts:
from survey import Survey
s = Survey(**globals())
concepts = [
{"id": "A", "brand": "Apple", "color": "Black", "network": "5G", "price": "$800"},
{"id": "B", "brand": "Apple", "color": "Blue", "network": "5G", "price": "$1000"},
{"id": "C", "brand": "Samsung", "color": "Black", "network": "4G", "price": "$600"},
{"id": "D", "brand": "Samsung", "color": "Silver", "network": "5G", "price": "$800"},
]
task_sets = {
"TS001": [["A", "C"], ["B", "D"], ["A", "D"], ["B", "C"]],
"TS002": [["A", "B"], ["C", "D"], ["A", "C"], ["B", "D"]],
}
s.conjoint_question(
question="Which product would you choose?",
concepts=concepts,
task_sets=task_sets,
required_tags=["brand", "color", "network", "price"],
none_option="None of these",
randomize=True,
tags={"study": "smartphone_cbc"},
)
s.complete()
Notes
- Each task response includes the selected concept and its reporting attributes.
- If
dont_know_optionis selected, it is treated as a fixed non-concept option (no concept tags are attached). - The Conjoint Analysis Design Tool produces both the
conceptsandtask_setsstructures; paste its output directly into the survey instead of writing them by hand. - See Choice-Based Conjoint for end-to-end study design and Utility and simulated share methodology for the reporting outputs.

