Documentation

Choice-Based Conjoint

Choice-based conjoint (CBC) is a survey technique for measuring how customers trade off product attributes when forced to pick between alternatives. Each respondent works through a sequence of tasks; in every task they see a small set of competing product concepts and choose the one they would actually buy. Analyzing the pattern of choices across tasks tells you how much each attribute level — brand, price, feature, packaging — contributes to preference, and lets you simulate share-of-preference across hypothetical market scenarios.

CBC complements profile-rating conjoint, which collects scored evaluations of one profile at a time. CBC's forced-choice format is closer to a real purchase decision and is the right tool when you want utility estimates and share simulations rather than absolute ratings. For the broader methodology arc and how the two approaches compare, see Setting up a conjoint study.

In MX8 Labs, the recommended implementation for CBC is the built-in conjoint_question method.

Bayesian reporting

Open the report editor's Analysis step and choose the calculation for the question:

  • Part Worth Scores shows the relative preference for each attribute level using the uncalibrated choice model.
  • Attribute Importance (%) compares each attribute's utility range with the total range across attributes.
  • Anchored Part Worth Scores and Anchored Attribute Importance (%) also use None of these answers or yes/no purchase follow-ups to account for whether respondents would buy a concept.
  • Marginal Purchase Lift requires yes/no purchase follow-ups. It estimates how purchase probability changes when you replace one attribute level while keeping the other attributes as they appeared in the study.

Include the attributes you want to analyze in required_tags. These calculations measure stated preferences, not actual sales.

Conjoint Analysis calculations with Anchored Part Worth Scores, Anchored Attribute Importance and Marginal Purchase Lift selected

The platform creates analysis reports with demographic columns automatically. You can also choose these calculations in your own cross-tabs. See Reporting with MX8 Labs for automatic reports and older saved calculations.

The conjoint report editor does not offer product-scenario simulations. Simulated Share is available for MaxDiff.

See Question aggregation types for calculation identifiers and Utility and simulated share methodology for estimation and uncertainty.

The examples below show the two anchored summaries for a study using an explicit none option. Part-worth scores have one row per attribute level; attribute importance has one row per attribute.

None-option anchored part-worth report with attribute-level scores and uncertainty whiskers

None-option anchored attribute importance report with a percentage for each tested attribute

Tip: Use the Conjoint Analysis Design Tool to design attributes/levels and generate the concept pool and task-set structure. You can paste its export straight into your survey description and the AI will program the conjoint_question call below from it.

Why Use conjoint_question

conjoint_question manages task assignment, comparison screens and answers:

  • Assigns one task set per respondent using least-fill balancing to keep per-task-set exposure roughly even.
  • Presents each task as a structured comparison of the task's concepts.
  • Keeps each choice and purchase follow-up linked to its task.
  • Supports both dict-backed concepts and media-backed concepts.

Method Signature

Code
s.conjoint_question( question, concepts, task_sets, concept_id_tag="id", required_tags=None, dont_know_option="", randomize=False, image_label_field=None, show_image_label=True, image_size=None, number_seconds=0, tags=None, id=None, none_option="", anchor_question=None, anchor_labels=None, )

Step 1: Create the Survey

python
from survey import Survey s = Survey(**globals())

Step 2: Define Concepts

Each concept must have a unique id (or your custom concept_id_tag). Add tags you want reported with each selected option.

Code
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"}, ]

Step 3: Define Task Sets

task_sets maps task-set ids to ordered tasks, where each task is a list of concept ids.

Code
task_sets = { "TS001": [["A", "C"], ["B", "D"], ["A", "D"], ["B", "C"]], "TS002": [["A", "B"], ["C", "D"], ["A", "C"], ["B", "D"]], }

Step 4: Ask the Conjoint Block

Code
choices = 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=s.tag(study="smartphone_cbc"), ) s.complete()

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.

Desktop conjoint task comparing Apple and Samsung by brand, color, network and price, with a None of these choice

The mobile chat experience also stacks concepts vertically, retaining their attribute labels and the separate None of these choice.

Mobile chat conjoint task with stacked Samsung and Apple concepts beneath the researcher header

The Conjoint Question reference also shows the traditional mobile layout.

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_question to 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:

Code
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:

Conjoint purchase follow-up asking Would you buy this option, with Yes and No responses

Response Behavior

  • The returned object is a dictionary-like response keyed by stable task IDs of the form "<exercise>:task-set:<task-set>:task:<number>".
  • Each task response includes:
    • The selected concept id.
    • required_tags values for dict-backed concepts.
    • Block tags (for example, study).
  • If dont_know_option is selected, it is treated as a fixed non-concept option (no concept tags attached).

Full Example

python
from survey import Survey s = Survey(**globals()) s.show_message( "You will see a series of product choices. In each task, select the option you would most likely buy." ) 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=s.tag(study="smartphone_cbc"), ) s.complete()