Documentation

API Reference

Article

API Reference

In the MX8 platform, surveys are written in Python using the Survey class.

Surveys should always start with the code block:

from survey import Survey

s = Survey(**globals())

You can import other Python libraries that are part of the standard library, e.g. datetime and math, but not modules that are not in the standard library, like pandas.

Survey

Survey class for creating surveys.

style

@property
style: Literal['traditional', 'chat']

Return the style of the survey.

Can be either 'traditional' or 'chat' depending on the configuration of the survey theme.

disable_bot_detection

disable_bot_detection() -> None

Disable bot detection mechanisms for this survey.

You should consider using this method if respondents are interacting with an interviewer who completes the survey, rather than responding on their own devices at home or work.

tag

tag(**kwargs: Any = {}) -> dict[str, Any]

Create tags for questions or temporary tag contexts.

Example

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

# Using as a context manager
with s.tag(brand="Ford", category="SUV"):
    s.text_question("What do you like about {brand} {category}s?")
    s.numeric_question("How many {brand} {category}s have you owned?")

# Passing directly to a question
s.text_question(
    "Why is {brand} your favorite?",
    tags=s.tag(brand=brand_name),
)

Parameters

NameTypeDescription
**kwargsAnyKey-value pairs to use as tags.

standard_screener

standard_screener(country: str | None = None, name: str = 'GenPop') -> None

Add a standard screener to the survey.

For many countries, MX8 has a standard screener that can be used to screen respondents. This is a standard set of questions that are used to screen respondents for the survey. The questions are standard demo questions and include weights to national averages.

Parameters

NameTypeDescription
countrystr | NoneThe country to use for the screener. This is the country code in the MX8 system. For example, "US" for the United States, "GB" for Great Britain, "AU" for Australia,
namestrThe name of the screener to use. This is the name of the screener in the MX8 system. The default is "GenPop".

show_message

show_message(
    message: str,
    image: MediaItem | None = None,
    require_response: bool = True,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> StringResponse | BoolResponse | IntResponse | ListResponse | None

Show a message to the user.

Presents a message to the user that they must acknowledge. This could be a introductory message, a warning, or any text based piece of information.

If require_response is set to False, then the message will be presented to the user, but they will not be required to acknowledge it.

Example

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

s.show_message("Welcome to our market research survey! Your feedback is"
       "important to us as it helps us understand market trends"
       "and consumer behavior. This survey is designed to gather"
       "information about your experiences and preferences related"
       "to our industry and company. Your responses will be kept"
       "confidential and used only for research purposes. Thank"
       "you for taking the time to participate!")

Parameters

NameTypeDescription
messagestrThe message to present to the user
require_responseboolWhether the user must acknowledge the message
imageMediaItem | NoneAn option image to show the user, from the s.media collection
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

get_consent

get_consent(
    consent_text: str | None = None,
    topic: str | None = None,
    client: str | None = None,
    image: MediaItem | None = None,
) -> BoolResponse

Get consent for the survey.

Asks the user the standard MX8 consent question. Terminates the respondent if they do not agree to the consent.

Example

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

s.get_consent()

Parameters

NameTypeDescription
topicstr | Nonethe topic to display in the consent question
clientstr | Nonethe description of the client to use for the consent question
consent_textstr | Noneoverride this value to set a custom text for the consent question
imageMediaItem | NoneAn option image to show the user, from the s.media collection

text_question

text_question(
    question: str,
    image: MediaItem | None = None,
    default: str | list[str] | None = None,
    short: bool = False,
    recodes: dict[str, str] | None = None,
    validation_instructions: str | None = None,
    quality_threshold: int = 3,
    termination_threshold: int = 1,
    max_attempts: int = 3,
    custom_validator: Callable[[Any], str | None] | None = None,
    number_of_responses: int = 1,
    min_responses: int | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> StringResponse | ListResponse

Add a text question to the survey.

Asks an open ended question to the respondent. The response is validated by AI according to the validation instructions and scored on a scale of 1-5. If the response does not meet the quality_threshold, the respondent will be asked to clarify their response. If after max_attempts the response does not meet the termination_threshold, the survey will terminate.

To prevent termination, set the quality_threshold to 1.

Example

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

s.text_question("When you think about cars, which brands immediately come to mind?")

Default values

If no default value is provided, the survey will generate a random string of 10 characters for the test data.

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

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.text_question(
        "What do you like about {brand} cars?",
        tags=s.tag(brand=brand),
    )

Custom Errors

Text questions by default are validated by AI to ensure that the response is a valid response. You can provide custom instructions for the validation by using the validation_instructions parameter.

By default, users are given 3 attempts to provide a valid response. If they fail to do so, the survey will terminate. You can change the maximum number of attempts by using the max_attempts parameter, and you can disable the termination by setting the terminate_after_max_attempts parameter to False.

If disabled, the validation error will be included in any calls to s.count_validation_errors().

If you do not want to use the AI validation, you can provide a custom_validator function that takes the response as a parameter and returns a string if the response is invalid. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

e.g. custom_validator=lambda x: "Are you sure you meant Sleepy Cows?" if x == "Sleepy Cows" else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
imageMediaItem | NoneAn option image to show the user, from the s.media collection
defaultstr | list[str] | Nonethe default answer to use in generating test data
shortboolwhether to use a short text input field
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
validation_instructionsstr | Nonea string describing validation rules for the question
quality_thresholdintthe minimum score (on a scale of 1-5) required for a valid response, defaults to 3
termination_thresholdintthe minimum score required to terminate, defaults to 1, e.g. no termination
max_attemptsintthe maximum number of attempts to get a valid response
custom_validatorCallable[[Any], str | None] | Nonea function to return a custom error message
number_of_responsesintthe number of responses to collect. Only supported in landscape orientation.
min_responsesint | Nonethe minimum number of responses to collect. Only supported in landscape orientation.
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

text_highlighter_question

text_highlighter_question(
    question: str,
    text_to_highlight: str,
    color: str = '#FFFF00',
    default: str | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> ListResponse

Add a text highlighter question to the survey.

Asks the respondent to highlight one or more parts of a given text.

Example

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

s.text_highlighter_question(
    "Please highlight the parts of the following text that you find most interesting:",
    text_to_highlight="The quick brown fox jumps over the lazy dog."
)

Default values

If no default value is provided, the survey will generate random highlights for the test data.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
text_to_highlightstrthe text that the respondent will highlight parts of
colorstrthe color to use for highlighting, in hex format
defaultstr | Nonethe default highlights to use in generating test data
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

numeric_question

numeric_question(
    question: str,
    image: MediaItem | None = None,
    min_max: tuple[int, int] = DEFAULT_MIN_MAX,
    default: int | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> IntResponse

Add a numeric question to the survey.

This presents the user with a numeric input for choosing a value between a range of numbers.

Example

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

s.numeric_question("What year were you born in?",
                   min_max=(1900, 2024))

Recodes

Recodes can be used to change the values of the responses.

Recodes for numeric question take the format of a dictionary where the key is the range of values to be recoded, and the value is the value to recode to. You can also use percentages to recode a percentage of the values.

Example

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

s.numeric_question("How old are you?",
                    min_max=(18, 100),
                    recodes={
                        "18-25": "18-25",
                        "26-54": "26-54",
                        "55-74": "55-74",
                        "75-100": "75+"
                    })

s.numeric_question("How many times have you visited our website?",
                    min_max=(0, 100),
                    recodes={
                        "0-30%": "Low",
                        "31-70%": "Medium",
                        "71-100%": "High"
                    })

Default values

If no default value is specified, then the test data will consist of random values between the min and max value.

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

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.numeric_question(
        "How many {brand} cars have you owned?",
        min_max=(0, 10),
        recodes={
            "0-30%": "Low",
            "31-70%": "Medium",
            "71-100%": "High",
        },
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention, e.g.

custom_validator=lambda x: "Are you sure that you're 150 years old" if x > 150 else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
min_maxtuple[int, int]the min and max range of the numbers
defaultint | Nonethe default value to use when generating test data.
imageMediaItem | NoneAn option image to show the user, from the s.media collection
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

select_question

select_question(
    question: str,
    options: list[str | MediaItem],
    image: MediaItem | None = None,
    randomize: bool = False,
    other_options: list[str] | None = None,
    disabled_options: list[str] | None = None,
    fixed_options: list[str] | None = None,
    specify_option: str | None = None,
    specify_text: str = DEFAULT_SPECIFY_TEXT,
    default: str | list[str] | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    skip_empty: bool = False,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    style: ChoiceQuestionStyle = 'default',
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> StringResponse

Add a multiple-choice question to the survey.

This presents the user with a number of choices from which the user can choose exactly one.

Example

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

s.select_question("What is your gender?",
                   options=["Male", "Female", "Non-Binary"])

Randomization

Set randomize to True to randomize the order of the options. If you have any additional options you do not want to have randomized, then you can specify these in the fixed_options parameter.

Default values

If no default value is specified, then the test data will consist of random values chosen from the options. If a list is provided, one value is sampled once when the question is created.

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question on a five point scale, but want to store the response on a three point scale, you can use recodes to map the response to the correct value.

Disabling Options

Options can be disabled using the disabled_options parameter. This is useful if you want to disable an option based on a previous response. For example, if you want to ask a question about what they enjoyed about the experience, and then ask about what they didn't enjoy, you can disable the options they selected in the first question.

Other, please specify

If you want to allow the user to specify an option that is not in the list, you can set the specify_option parameter. This will present the user with an additional option to specify their own value.

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

s.select_question("On a scale of 1 to 5, how much do you like this product?",
    options=["1", "2", "3", "4", "5"],
    recodes={
        "1": "dislike",
        "2": "dislike",
        "3": "neutral",
        "4": "like",
        "5": "like"})
from survey import Survey
s = Survey(**globals())

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.select_question(
        "How many {brand} cars have you owned?",
        options=["0", "1", "2", "3", "4+"],
        recodes={
            "0": "never owned",
            "1": "single owner",
            "2": "loyalist",
            "3": "loyalist",
            "4+": "enthusiast",
        },
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

e.g. custom_validator=lambda x: "Are you sure you meant Sleepy Cows?" if x == "Sleepy Cows" else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
optionslist[str | MediaItem]a list of strings or items from s.media containing the options
imageMediaItem | NoneAn option image to show the user, from the s.media collection
randomizeboolwhether to randomize the order of the options
other_optionslist[str] | Nonea list of additional options to present to the user
disabled_optionslist[str] | Nonea list of strings containing options to be disabled
fixed_optionslist[str] | Nonea list of strings containing the fixed options
skip_emptyboolif set to True, the question will be skipped if there are no options
specify_optionstr | NoneAn 'other' that the user will be asked to specify
specify_textstrThe text to ask the user to specify the 'other' option, defaults to "Please specify"
defaultstr | list[str] | Nonethe default value(s) to use when generating test data.
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the options
show_image_labelboolwhether to show the image label or just to show the image
image_sizetuple[int, int] | Nonethe bounding box size of the image to display
styleChoiceQuestionStylepresentation style for the options.
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

multi_select_question

multi_select_question(
    question: str,
    options: list[str | MediaItem],
    max_options: int | None = None,
    image: MediaItem | None = None,
    randomize: bool = False,
    other_options: list[str] | None = None,
    disabled_options: list[str] | None = None,
    fixed_options: list[str] | None = None,
    exclusive_options: list[str] | None = None,
    specify_option: str | None = None,
    specify_text: str = DEFAULT_SPECIFY_TEXT,
    default: list[str] | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    skip_empty: bool = False,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    style: ChoiceQuestionStyle = 'default',
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> ListResponse

Add a multi-select question to the survey.

This presents the user with a number of choices from which the user can choose one or more.

Example

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

s.select_question("What is your gender?",
                   options=["Male", "Female", "Non-Binary"])

Randomization

Set randomize to True to randomize the order of the options. If you have any additional options you do not want to have randomized, then you can specify these in the fixed_options parameter.

Default values

If no default value is specified, then the test data will consist of random values chosen from the options.

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and classify it into different categories, you can use recodes to map the response to the correct value.

Disabled Options

Options can be disabled using the disabled_options parameter. This is useful if you want to disable an option based on a previous response. For example, if you want to ask a question about what they enjoyed about the experience, and then ask about what they didn't enjoy, you can disable the options they selected in the first question.

Other, please specify

If you want to allow the user to specify an option that is not in the list, you can set the specify_option parameter. This will present the user with an additional option to specify their own value.

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

enjoyment = s.multi_select_question("What did you enjoy about the experience?",
    options=["The food", "The service", "The atmosphere", "The price"],
    fixed_options=["Other"],
    exclusive_options=["Other"],
    recodes={
        "The food": "food",
        "The service": "service",
        "The atmosphere": "atmosphere",
        "The price": "price",
        "Other": "other"})

if "Other" in enjoyment:
    s.text_question("What else did you enjoy about the experience?")
from survey import Survey
s = Survey(**globals())

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.select_question(
        "Which of the following do you associate with {brand} cars?",
        options=["Reliability", "Safety", "Performance", "Luxury"],
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

e.g. custom_validator=lambda x: "Are you sure you meant Sleepy Cows?" if "Sleepy Cows" in x else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
optionslist[str | MediaItem]a list of strings or items from s.media containing the options
max_optionsint | Nonethe maximum number of options to be selected, defaults to all options
imageMediaItem | NoneAn option image to show the user, from the s.media collection
randomizeboolwhether to randomize the order of the options
other_optionslist[str] | Nonea list of additional options to present to the user
disabled_optionslist[str] | Nonea list of strings containing options to be disabled
fixed_optionslist[str] | Nonea list of strings containing the fixed options
exclusive_optionslist[str] | Nonea list of strings containing the exclusive options
specify_optionstr | NoneAn 'other' that the user will be asked to specify
specify_textstrThe text to ask the user to specify the 'other' option, defaults to "Please specify"
skip_emptyboolif set to True, the question will be skipped if there are no options
defaultlist[str] | Nonethe default value to use when generating test data.
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the options
show_image_labelboolwhether to show the image label or just to show the image
image_sizetuple[int, int] | Nonethe bounding box size of the image to display
styleChoiceQuestionStylepresentation style for the options.
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

grid_select_question

grid_select_question(
    question: str,
    rows: list[str | MediaItem],
    row_name: str,
    options: list[str | MediaItem],
    style: GridSelectStyle = 'radio',
    randomize: bool = False,
    randomize_options: bool = False,
    other_options: list[str] | None = None,
    fixed_options: list[str] | None = None,
    specify_option: str | None = None,
    specify_text: str = DEFAULT_SPECIFY_TEXT,
    image: MediaItem | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    skip_empty: bool = False,
    default: dict[str, str | list[str]] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a grid select question to the survey.

This presents the user with a grid of options where they can select one option from each row.

Example

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

s.grid_select_question(
    "Please rate the following aspects of the product",
    row_name="Product Aspect",
    rows=["Quality", "Price", "Service", "Delivery"],
    options=["Poor", "Fair", "Good", "Very Good", "Excellent"],
)

Recodes: Recodes map responses to different values. This is useful when you want to classify responses into categories.

s.grid_select_question(
    "Please rate the following aspects of the product",
    row_name="Product Aspect",
    rows=["Quality", "Price", "Service", "Delivery"],
    options=["Poor", "Fair", "Good", "Very Good", "Excellent"],
    recodes={
        "Poor": "1",
        "Fair": "2",
        "Good": "3",
        "Very Good": "4",
        "Excellent": "5",
    },
)

Custom Errors: By default, custom_validator is set to a straight-line check that raises an error if the respondent enters the same value for each cell. You can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrThe question to ask the respondent.
rowslist[str | MediaItem]Strings or media items containing the rows.
row_namestrLabel to use for each row in topics.
optionslist[str | MediaItem]Strings or media items containing the options.
styleGridSelectStyleThe style of the question ("button" or "radio"). Defaults to "radio".
randomizeboolWhether to randomize the order of the rows.
randomize_optionsboolWhether to randomize the order of the options.
other_optionslist[str] | NoneAdditional options to present to the user.
fixed_optionslist[str] | NoneFixed options that should not be randomized.
specify_optionstr | NoneAn "other" option that the user will be asked to specify.
specify_textstrThe text to ask the user to specify the "other" option.
imageMediaItem | NoneAn option image to show the user, from the s.media collection.
recodesdict[str, str] | NoneA dictionary of recodes to apply to the question.
custom_validatorCallable[[str], str] | NoneA function that returns a custom error message.
image_label_fieldstr | NoneThe field to use as the label for media items in the rows.
show_image_labelboolWhether to show the image label or just the image in the rows.
image_sizetuple[int, int] | NoneThe bounding box size of the image to display.
skip_emptyboolIf True, skip the question when there are no rows or options.
defaultdict[str, str | list[str]] | NonePer-row defaults; list values are sampled once at creation.
tagsdict[str, Any] | NoneTags to attach to this question, from s.tag(...).
**_kwargsAnyAdditional question configuration.

grid_multi_select_question

grid_multi_select_question(
    question: str,
    rows: list[str | MediaItem],
    row_name: str,
    options: list[str | MediaItem],
    style: GridMultiSelectStyle = 'checkbox',
    randomize: bool = False,
    randomize_options: bool = False,
    other_options: list[str] | None = None,
    fixed_options: list[str] | None = None,
    exclusive_options: list[str] | None = None,
    specify_option: str | None = None,
    specify_text: str = DEFAULT_SPECIFY_TEXT,
    image: MediaItem | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    skip_empty: bool = False,
    default: dict[str, list[str]] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a grid multi-select question to the survey.

This presents the user with a grid of options where they can select multiple option from each row.

Example

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

s.grid_multi_select_question("What do you associate with these brands? Select all that apply",
    rows=["Coke", "Pepsi", "Dasani", "Fanta"],
    options=["Tasty", "Refreshing", "Cool", "Value", "Convenient"])

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and classify it into different categories, you can use recodes to map the response to the correct value.

Example

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

s.grid_multi_select_question("What do you associate with these brands? Select all that apply",
    row_name="Brand",
    rows=["Coke", "Pepsi", "Dasani", "Fanta"],
    options=["Tasty", "Refreshing", "Cool", "Value", "Convenient"],
    recodes={
        "Tasty": "Product",
        "Refreshing": "Product",
        "Cool": "Brand",
        "Value": "Pricing",
        "Convenient": "Distribution"
    })

Custom Errors

By default, the custom_validator parameter is set to a straight-line check that raises an error if the respondent enters the same value for each cell but you can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
rowslist[str | MediaItem]the rows to show in the grid
row_namestrthe name of the row
optionslist[str | MediaItem]the options available for each row
styleGridMultiSelectStylethe question style, either "button" or "checkbox"; defaults to "checkbox"
randomizeboolwhether to randomize the order of the rows
randomize_optionsboolwhether to randomize the order of the options
other_optionslist[str] | Noneadditional options to present to the user
fixed_optionslist[str] | Noneoptions that should remain fixed in place
exclusive_optionslist[str] | Noneoptions that should be mutually exclusive
specify_optionstr | Nonean "other" option that the user will be asked to specify
specify_textstrthe prompt used when the respondent specifies the "other" option
imageMediaItem | Nonean option image to show the user, from the s.media collection
recodesdict[str, str] | Nonea dictionary of recodes to use on this question
defaultdict[str, list[str]] | Nonedefault values to use when generating test data
skip_emptyboolif True, skip the question when there are no rows
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the rows
show_image_labelboolwhether to show the image label or just to show the image in the rows
image_sizetuple[int, int] | Nonethe bounding box size of the image to display
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

grid_rating_question

grid_rating_question(
    question: str,
    rows: list[str | MediaItem],
    row_name: str,
    image: MediaItem | None = None,
    number_of_points: int | None = None,
    style: RatingQuestionStyle = 'slider',
    first_point: int | None = None,
    labels: dict[int, str] | None = None,
    randomize: bool = False,
    recodes: dict[str, str] | None = None,
    dont_know_option: str = '',
    skip_empty: bool = False,
    custom_validator: Callable[[str], str] | None = None,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    default: dict[str, int] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a grid rating question to the survey.

This presents the user with a grid of options where they can rate each row on user defined scale.

Example

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

s.grid_rating_question("Please rate the following aspects of the product",
    rows=["Quality", "Price", "Service", "Delivery"],
    row_name="Product Aspect",
    number_of_points=5)

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and classify it into different categories, you can use recodes to map the response to the correct value.

Example

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

s.grid_rating_question("Please rate the following aspects of the product",
    row_name="Product Aspect",
    rows=["Quality", "Price", "Service", "Delivery"],
    number_of_points=5,
    recodes={
        "1": "Poor",
        "2": "Poor",
        "3": "Fair",
        "4": "Fair",
        "5": "Good"
    })

Custom Errors

By default, the custom_validator parameter is set to a straight-line check that raises an error if the respondent enters the same value for each cell but you can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
rowslist[str | MediaItem]a list of strings or items from s.media containing the rows
row_namestrthe name of the row
imageMediaItem | NoneAn option image to show the user, from the s.media collection
number_of_pointsint | Nonethe number of points to rate the row on, defaults to 5 or the number of labels
styleRatingQuestionStylethe style of the question, either "slider", "button" or "star"
first_pointint | Nonethe value of the first point, defaults to 1 or the first label
labelsdict[int, str] | Nonea dictionary of labels to use on the question
randomizeboolwhether to randomize the order of the rows
defaultdict[str, int] | Nonea dictionary of default values to use when generating test data
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
dont_know_optionstrlabel to use for the don't-know option, if any.
skip_emptyboolif set to True, the question will be skipped if there are no rows
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the rows
show_image_labelboolwhether to show the image label or just to show the image in the rows
image_sizetuple[int, int] | Nonethe bounding box size of the images to display
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

grid_numeric_question

grid_numeric_question(
    question: str,
    rows: list[str | MediaItem],
    row_name: str,
    columns: list[str] | None = None,
    column_name: str | None = None,
    image: MediaItem | None = None,
    min_max: tuple[int, int] = DEFAULT_MIN_MAX,
    randomize: bool = False,
    randomize_columns: bool = False,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[int], str] | None = None,
    autosum_columns: bool = False,
    autosum_rows: bool = False,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    default: dict[str, int | dict[str, int]] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a grid numeric question to the survey.

This presents the user with a grid of options where they can select one option from each row.

Example

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

s.grid_numeric_question("How many hours do you spend per week on the following activities?",
    rows=["Work", "Sleep", "Exercise", "Socializing"],
    row_name="Activity",
    columns=["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
    randomize=True,
    )

Recodes

Recodes can be used to change the values of the responses.

Recodes for numeric question take the format of a dictionary where the key is the range of values to be recoded, and the value is the value to recode to. You can also use percentages to recode a percentage of the values.

Example

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

s.grid_numeric_question("How many hours do you spend per week on the following activities?",
    rows=["Work", "Sleep", "Exercise", "Socializing"],
    row_name="Activity",
    columns=["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
    randomize=True,
    recodes={
        "0-30%": "Low",
        "31-70%": "Medium",
        "71-100%": "High"
    })

Custom Errors

By default, the custom_validator parameter is set to a straight-line check that raises an error if the respondent enters the same value for each cell but you can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
rowslist[str | MediaItem]a list of strings containing the rows
row_namestrthe name of the row
columnslist[str] | Nonea list of strings containing the columns
column_namestr | Nonethe name of the column
imageMediaItem | NoneAn option image to show the user, from the s.media collection
min_maxtuple[int, int]the minimum and maximum values for the question
randomizeboolbool: whether to randomize the order of the rows
randomize_columnsbool(bool): whether to randomize the order of the columns
recodesdict[str, str] | Nonea dictionary of recodes to use on this question.
defaultdict[str, int | dict[str, int]] | Nonea dictionary of default values to use when generating test data
autosum_columnsboolwhether to autosum the columns
autosum_rowsboolwhether to autosum the rows
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the rows
show_image_labelboolwhether to show the image label or just to show the image in the rows
image_sizetuple[int, int] | Nonethe bounding box size of the images to display
custom_validatorCallable[[int], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

this_or_that_question

this_or_that_question(
    question: str,
    row_options: list[list[str | MediaItem]],
    randomize: bool = False,
    randomize_columns: bool = False,
    default: dict[str, str | list[str]] | None = None,
    recodes: dict[str, str] | None = None,
    image: MediaItem | None = None,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    custom_validator: Callable[[int], str] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a this or that question to the survey.

This presents the user with a series of questions where they can select one option from each row.

Example

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

s.this_or_that_question("Which of the following do you prefer?",
    row_options=[
        ["Apples", "Oranges"],
        ["Coke", "Pepsi"],
        ["Dogs", "Cats"],
        ["Winter", "Summer"]
    ])

Recodes

Recodes can be used to change the values of the responses.

Recodes for this or that question take the format of a dictionary where the key is the range of values to be recoded, and the value is the value to recode to. You can also use percentages to recode a percentage of the values.

Example

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

s.this_or_that_question("Which of the following do you prefer?",
    row_options=[
        ["Apples", "Oranges"],
        ["Coke", "Pepsi"],
        ["Dogs", "Cats"],
        ["Winter", "Summer"]
    ])

Custom Errors

By default, the custom_validator parameter is set to a straight-line check that raises an error if the respondent enters the same value for each cell but you can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
row_optionslist[list[str | MediaItem]]a list of lists containing the options
randomizeboolbool: whether to randomize the order of the rows
randomize_columnsbool(bool): whether to randomize the order of the columns
recodesdict[str, str] | Nonea dictionary of recodes to use on this question.
defaultdict[str, str | list[str]] | Noneper-row defaults; list values are sampled once at creation
imageMediaItem | NoneAn option image to show the user, from the s.media collection
image_label_fieldstr | Nonethe label to show above the image
show_image_labelboolwhether to show the image label or just to show the image in the rows
image_sizetuple[int, int] | Nonethe bounding box size of the images to display
custom_validatorCallable[[int], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

this_or_that_rating_question

this_or_that_rating_question(
    question: str,
    row_options: list[list[str]],
    row_name: str = 'scale',
    number_of_points: int | None = None,
    style: ThisOrThatRatingStyle = 'slider',
    first_point: int | None = None,
    dont_know_option: str = '',
    randomize: bool = False,
    default: dict[str, int] | None = None,
    recodes: dict[str, str] | None = None,
    image: MediaItem | None = None,
    custom_validator: Callable[[int], str] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a this or that rating question to the survey.

This presents the user with a series of questions where they can rate one option from each row.

Example

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

s.this_or_that_rating_question("Which of the following do you prefer?",
    number_of_points=5,
    row_options=[
        ["Apples", "Oranges"],
        ["Coke", "Pepsi"],
        ["Dogs", "Cats"],
        ["Winter", "Summer"]
    ])

Recodes

Recodes can be used to change the values of the responses.

Recodes for this or that question take the format of a dictionary where the key is the range of values to be recoded, and the value is the value to recode to. You can also use percentages to recode a percentage of the values.

Example

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

s.this_or_that_rating_question("Which of the following do you prefer?",
    row_options=[
        ["Apples", "Oranges"],
        ["Coke", "Pepsi"],
        ["Dogs", "Cats"],
        ["Winter", "Summer"]
    ])

Custom Errors

By default, the custom_validator parameter is set to a straight-line check that raises an error if the respondent enters the same value for each cell but you can override this by passing a custom validator function.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
row_optionslist[list[str]]a list of lists containing the options
row_namestrthe name of the row (default "scale")
number_of_pointsint | Nonethe number of points to rate the row on, defaults to 5
styleThisOrThatRatingStylethe style of the question, either "slider" or "button"
first_pointint | Nonethe value of the first point, defaults to 1
dont_know_optionstrOptionally add a "Don't know" option to the question using this text.
randomizeboolbool: whether to randomize the order of the rows
recodesdict[str, str] | Nonea dictionary of recodes to use on this question.
defaultdict[str, int] | Nonea dictionary of default values to use when generating test data
imageMediaItem | NoneAn option image to show the user, from the s.media collection
custom_validatorCallable[[int], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

show_image

show_image(image: MediaItem, number_seconds: int = 5) -> StringResponse | BoolResponse | IntResponse | ListResponse | None

Show an image to the respondent.

This will show an image to the respondent for a set number of seconds.

Example

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

for media in s.media:
    s.show_image("Take a look at this image for 5 seconds",
                image=media,
                number_seconds=5)

Parameters

NameTypeDescription
imageMediaItemthe image to show
number_secondsintthe number of seconds to show the image for

play_video

play_video(
    video: MediaItem,
    end_message: str = 'Thank you for watching the video!',
    start_message: str = "Hit play when you're ready to watch the video.",
    dial: str = 'none',
    dial_labels: dict[int, str] | None = None,
    dial_caption: str = 'Please adjust the slider to reflect your feelings as you watch the video.',
    start_position: int | None = None,
) -> StringResponse | BoolResponse | IntResponse | ListResponse | None

Play a video to the respondent.

This will play a video to the respondent and then present them with a message at the end, which defaults to "Thank you for watching the video!".

The Video is automatically watermarked with the user's IP address if the security parameter is set to True and always DRM protected to prevent copying or screen recording. Links to the video are only valid for 60 seconds.

Example

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

for media in s.media:
    s.play_video(video=media)

    ... now ask questions about the video

Dial testing

You can also add a dial to the video to allow the respondent to indicate their feelings as they watch the video. The dial can be set to one of the following values:

  • "none" - no dial is shown
  • "right" - a dial is shown on the right of the video
  • "bottom" - a dial is shown at the bottom of the video

The dial defaults to a range of 0-100, with captions "Dislike", "Neutral", and "Like" but you can set the labels and caption for the dial using the dial_labels and dial_caption parameters.

Parameters

NameTypeDescription
videoMediaItemthe video to play
end_messagestrthe message to show the respondent at the end of the video
start_messagestrthe message to show the respondent at the start of the video
dialstrthe position of the dial, either "none", "right", or "bottom", defaults to "none"
dial_labelsdict[int, str] | Nonethe labels to show on the dial
dial_captionstrthe caption to show above the dial
start_positionint | Nonestarting value for the dial; defaults to the midpoint of the dial labels

show_embedded_media

show_embedded_media(question: str, url: str, duration: int) -> StringResponse

Show embedded content from a URL in the survey.

Currently only supports embedding content from YouTube.

Example

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

s.show_embedded_media("Watch this video", "https://www.youtube.com/watch?v=2gcsgfzqN8k", duration=231)

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
urlstrthe URL to embed in the survey
durationintthe number of seconds to wait before allowing the user to continue

get_location

get_location(
    validation_type: str | None = None,
    reporting_type: str | None = None,
    default: str | None = None,
    number_options: int = 5,
    tags: dict[str, Any] | None = None,
    strict: bool = False,
    **_kwargs: Any = {},
) -> StringResponse

Get the location of the user.

Adds two questions to the survey. The first asks for the users zipcode and the second validates the zipcode based on the validation_type. The location is reported based on the reporting_type.

Example

s.get_location(validation_type="state", default="90210")

Default values

If no default value is specified, then the test data will consist of random values chosen from the options.

Recodes

The location question does not support recodes.

Parameters

NameTypeDescription
validation_typestr | Nonethe type of location to validator with, defaults to city
reporting_typestr | Nonethe type of location to report, defaults to region
defaultstr | Nonethe default value to look
number_optionsintthe number of options to show the user
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.
strictboolwhether to terminate the respondent if the respondent enters invalid data

quota

quota(
    name: str,
    criteria: bool,
    quota: float = 0.0,
    min_respondents: int = 0,
    max_respondents: int | None = None,
) -> Quota

Create a quota element.

Used to create an individua quota line that makes up part of a quota.

Example

from survey import Survey

s = Survey(**globals())

age = s.numeric_question(question="How old are you?",
                        min_max=(18, 100),
                        recodes={
                            "0-17": "Under 18",
                            "18-34": "18-34",
                            "35-54": "35-54",
                            "55-120": "55+"
                        })

gender = s.select_question(question="What is your gender?",
                                options=["Male", "Female"])

#### Check age and gender quotas
s.set_quota(
    name="Quads",
    quotas=[
        s.quota("Younger Men", criteria=(age < 40) & (gender == "Male"), quota=0.25),
        s.quota("Older Men", criteria=(age >= 40) & (gender == "Male"), quota=0.25),
        s.quota("Younger Women", criteria=(age < 40) & (gender == "Female"), quota=0.25),
        s.quota("Older Women", criteria=(age >= 40) & (gender == "Female"), quota=0.25)
    ]
)

You can also specify a minimum number of respondents that must be included in this quota line by passing the min_respondents parameter.

Example

from survey import Survey
s = Survey(**globals())
s.set_quota(
    name="Age Quota",
    quotas=[
        s.quota("Under 18", criteria=(age < 18), quota=0.1, min_respondents=50),
        s.quota("18-34", criteria=(age >= 18) & (age < 35), quota=0.3, min_respondents=100),
        s.quota("35-54", criteria=(age >= 35) & (age < 55), quota=0.3, min_respondents=100),
        s.quota("55+", criteria=(age >= 55), quota=0.3, min_respondents=100)
    ]
)

If you only pass in values with min_respondents, then the quota will not be used for weighting, but it will still be used to terminate respondents that do not meet the criteria.

You can optionally set max_respondents to cap the number of respondents assigned to a quota line. If omitted, that line has no explicit cap.

Parameters

NameTypeDescription
namestrthe name to give this quota line when it is reported
criteriaboolthe boolean condition based on responses to other questions that the respondent must meet to be included in this quota line
quotafloatthe proportion of respondents that should fall into this quota
min_respondentsintthe minimum number of respondents that must be included in this quota line
max_respondentsint | Noneoptional maximum number of respondents for this quota line

set_quota

set_quota(name: str, quotas: list[Quota], exclusive: bool = True) -> QuotaResponse

Set a quota group based on a number of quota lines.

Takes a group of individual quotas from s.quota() and creates a group that each respondent must fall into at least one category. Any respondents that do not fall into one of the groups, or respondents that are over-quota, will be terminated.

Example

from survey import Survey

s = Survey(**globals())

age = s.numeric_question(question="How old are you?",
                        min_max=(18, 100),
                        recodes={
                            "0-17": "Under 18",
                            "18-34": "18-34",
                            "35-54": "35-54",
                            "55-120": "55+"
                        })

gender = s.select_question(question="What is your gender?",
                                options=["Male", "Female"])

#### Check age and gender quotas
s.set_quota(
    name="Quads",
    quotas=[
        s.quota("Younger Men", criteria=(age < 40) & (gender == "Male"), quota=0.25),
        s.quota("Older Men", criteria=(age >= 40) & (gender == "Male"), quota=0.25),
        s.quota("Younger Women", criteria=(age < 40) & (gender == "Female"), quota=0.25),
        s.quota("Older Women", criteria=(age >= 40) & (gender == "Female"), quota=0.25)
    ]
)

Parameters

NameTypeDescription
namestrthe name of this group of quotas, for example "demos"
quotaslist[Quota]a list of quotas to be added, each created using s.quota()
exclusiveboolwhether the quotas are exclusive, defaults to True. If set to False, then respondents can be included in multiple quota lines, but they will still be terminated if they do not meet any of the quota criteria.

get_least_filled

get_least_filled(number: int, from_list: list[Any], quota: str) -> list[Any]

Get the least filled quotas from a list of elements in a quota.

If you want to ask about a large number of items and you want to make sure that you have a minimum number of respondents for each item, then you can use this function to get the least filled items from a list of items.

Note that this function will return the least filled items from the list, and will not terminate the respondent based on the number of other respondents that have already selected those items. If you want to terminate the respondent based on the number of other respondents that have already selected those items, then you should use the set_quota() function to establish the quotas.

Example

from survey import Survey

s = Survey(**globals())

brand_list = ['Acura', 'Alfa Romeo', 'Aston Martin', 'Audi', 'Bentley',
              'BMW', 'Bugatti', 'Buick', 'Cadillac', 'Chevrolet', 'Chrysler',
              'Citroen', 'Dodge', 'Ferrari', 'Fiat', 'Ford', 'Geely', 'Genesis',
              'GMC', 'Honda', 'Hyundai', 'Infiniti', 'Jaguar', 'Jeep', 'Kia',
              'Koenigsegg', 'Lamborghini', 'Land Rover', 'Lexus', 'Lincoln',
              'Lotus', 'Maserati', 'Mazda', 'McLaren', 'Mercedes-Benz', 'Mini',
              'Mitsubishi', 'Nissan', 'Pagani', 'Peugeot', 'Polestar', 'Porsche',
              'Ram', 'Renault', 'Rolls-Royce', 'Subaru', 'Suzuki', 'Tesla', 'Toyota',
              'Volkswagen', 'Volvo']


brands = s.get_least_filled(number=10,
                            from_list=brand_list,
                            quota="Brand familiarity")

familiar_brands = s.multi_select_question(
    question="Which of the following car brands have you heard of?",
    options=brands)

Parameters

NameTypeDescription
numberintthe number of items to return
from_listlist[Any]the list of items to choose from
quotastrthe name of the quota to check against

terminate

terminate(reason: str) -> NoReturn

Terminate the survey.

Call this function if a condition has been met that means you want to terminate the survey, for example if the consumer does not qualify for a specific reason.

If you are wanting to set quotas, you should us the set_quota function which also terminats if respondents do not qualify for the quotas

Example

if has_xbox = False:
    s.terminate("Sorry you don't qualify for this survey"
                "because you don't have an Xbox")

Parameters

NameTypeDescription
reasonstrThe reason to give to the user to explain why they don't qualify.

terminate_if

terminate_if(condition: bool, reason: str) -> None

Terminate the survey if a condition is met.

Call this function with the condition you want to check and then terminate the user if the condition is true.

Example

if s.terminate_if(has_xbox = False, "Sorry you don't qualify for this survey"
                  "because you don't have an Xbox")

Parameters

NameTypeDescription
conditionboolThe condition to check and terminate the user if it's True
reasonstrThe reason to give to the user to explain why they don't qualify.

complete

complete() -> None

Complete the survey.

Call this function at the end of the survey to complete the survey and thank the user.

Example

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

# Add questions here

s.complete()

rating_question

rating_question(
    question: str,
    image: MediaItem | None = None,
    number_of_points: int | None = None,
    style: RatingQuestionStyle = 'slider',
    first_point: int | None = None,
    labels: dict[int, str] | None = None,
    default: int | None = None,
    recodes: dict[str, str] | None = None,
    dont_know_option: str = '',
    custom_validator: Callable[[str], str] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> IntResponse

Add a rating question to the survey.

This presents the user with a number of choices of which the user can choose one that represents their opinion on a sliding scale.

There are three available styles:

  • style="slider" - For the slider style, the user can drag the slider.
  • style="button" - For the button style, the user can click on the button they want.

In both the slider and button styles, the rating scale is presented as a number with optional text labels for appropriate points on the scale.

Example

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

s.rating_question("How much do you like this product?",
                  number_of_points=5,
                  style="slider",
                  labels={
                      1: "Dislike",
                      3: "Neutral",
                      5: "Like"
                  })

Default values

If no default value is specified, then the test data will consist of random values chosen from the options.

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and classify it into different categories, you can use recodes to map the top two box response to a different value.

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

s.rating_question("On a scale of 1 to 5, how much do you like this product?",
    number_of_points=5,
    style="slider",
    labels={
        1: "Dislike",
        3: "Neutral",
        5: "Like"
    },
    recodes={
        "1": "dislike",
        "2": "dislike",
        "3": "neutral",
        "4": "like",
        "5": "like"})

Using the don't know option

If you want to add a "Don't know" option to the question, then you can specify the text to use for the "Don't know" option using the dont_know_option parameter. If the user selects this option then the response will be recorded as a value of -999 in the survey data and reported as the text specified in the dont_know_option parameter.

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

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.rating_question(
        "How do you rate {brand} cars?",
        number_of_points=5,
        style="slider",
        labels={1: "Dislike", 3: "Neutral", 5: "Like"},
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
number_of_pointsint | Nonethe number of points on the scale (default to 5 or the number of labels)
first_pointint | Nonethe first point on the scale (default to 1 or the first label)
styleRatingQuestionStylethe style of the scale, either "slider", "button", or "star"
labelsdict[int, str] | Nonea dictionary of text labels for each point on the scale
imageMediaItem | NoneAn option image to show the user, from the s.media collection
defaultint | Nonethe default value to use when generating test data.
dont_know_optionstrOptionally add a "Don't know" option to the question using this text.
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

net_promoter_score_question

net_promoter_score_question(
    question: str,
    image: MediaItem | None = None,
    number_of_points: int | None = 11,
    style: RatingQuestionStyle = 'slider',
    first_point: int | None = None,
    labels: dict[int, str] | None = None,
    default: int | None = None,
    recodes: dict[str, str] | None = None,
    dont_know_option: str = '',
    custom_validator: Callable[[str], str] | None = None,
    min_promoter_score: int | None = None,
    max_detractor_score: int | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> IntResponse

Add a rating question to the survey.

This presents the user with a number of choices of which the user can choose one that represents their opinion on a sliding scale.

There are three available styles:

  • style="slider" - For the slider style, the user can drag the slider.
  • style="button" - For the button style, the user can click on the button they want.

In both the slider and button styles, the rating scale is presented as a number with optional text labels for appropriate points on the scale.

Example

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

s.net_promoter_score_question("How much do you like this product?",
                  number_of_points=11,
                  style="slider",
                  labels={
                      1: "Dislike",
                      3: "Neutral",
                      5: "Like"
                  })

Default values

If no default value is specified, then the test data will consist of random values chosen from the options.

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and classify it into different categories, you can use recodes to map the top two box response to a different value.

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

s.net_promoter_score_question("On a scale of 1 to 5, how much do you like this product?",
    number_of_points=5,
    style="slider",
    labels={
        1: "Dislike",
        3: "Neutral",
        5: "Like"
    },
    recodes={
        "1": "dislike",
        "2": "dislike",
        "3": "neutral",
        "4": "like",
        "5": "like"})

Using the don't know option

If you want to add a "Don't know" option to the question, then you can specify the text to use for the "Don't know" option using the dont_know_option parameter. If the user selects this option then the response will be recorded as a value of -999 in the survey data and reported as the text specified in the dont_know_option parameter.

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

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

for brand in car_brands:
    s.net_promoter_score_question(
        "How do you rate {brand} cars?",
        number_of_points=5,
        style="slider",
        labels={1: "Dislike", 3: "Neutral", 5: "Like"},
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
number_of_pointsint | Nonethe number of points on the scale (default to 5 or the number of labels)
first_pointint | Nonethe first point on the scale (default to 1 or the first label)
styleRatingQuestionStylethe style of the scale, either "slider", "button", or "star"
labelsdict[int, str] | Nonea dictionary of labels (default {0:"Not at all likely", 10:"Extremely likely"})
imageMediaItem | NoneAn option image to show the user, from the s.media collection
defaultint | Nonethe default value to use when generating test data.
dont_know_optionstrOptionally add a "Don't know" option to the question using this text.
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
min_promoter_scoreint | Noneminimum score need for promoter (default to 9)
max_detractor_scoreint | Noneminimum score need for detractor (default to 6)
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

ranking_question

ranking_question(
    question: str,
    options: list[str | MediaItem],
    min_options: int | None = None,
    max_options: int | None = None,
    style: ChoiceQuestionStyle = 'button',
    labels: tuple[str, str] = ('Least', 'Most'),
    randomize: bool = False,
    fixed_options: list[str] | None = None,
    other_options: list[str] | None = None,
    skip_empty: bool = False,
    default: list[str] | None = None,
    recodes: dict[str, str] | None = None,
    custom_validator: Callable[[str], str] | None = None,
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    dont_know_option: str = '',
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> ListResponse

Add a ranking question to the survey.

This presents the user with a number of choices of which the user must rank in order of preference.

Example

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

s.ranking_question("Rank the following car brands in order of preference",
                    options=["Ford", "Toyota", "Honda", "Tesla"],
                    labels=("Least", "Most"),

Default values

If no default value is specified, then the test data will consist of the options returned in a random order.

Recodes

Recodes are used to map the response to a different value. This is useful for when you want to map a response to a different value. For example, if you want to ask a question about what they enjoyed about the experience, and ranks the different activities, you can use recodes to map the top two box response to a different value.

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

s.ranking_question("Rank the following activities in order of preference",
                    options=["Eating", "Drinking", "Sleeping", "Working"],
                    labels=("Least", "Most"),
                    recodes={
                        "Eating": "eating",
                        "Drinking": "drinking",
                        "Sleeping": "sleeping",
                        "Working": "working"
                    })
from survey import Survey
s = Survey(**globals())

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

brand_cars = {
    "Ford": ["Fiesta", "Focus", "Mustang", "F150"],
    "Toyota": ["Corolla", "Camry", "Prius", "RAV4"],
    "Honda": ["Civic", "Accord", "CR-V", "Pilot"],
    "Tesla": ["Model S", "Model 3", "Model X", "Model Y"],
}

for brand in car_brands:
    s.ranking_question(
        "Rank the following {brand} cars in order of preference?",
        options=brand_cars[brand],
        labels=("Least", "Most"),
        tags=s.tag(brand=brand),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

e.g. custom_validator=lambda x: "Are you sure you meant Sleepy Cows?" if "Sleepy Cows" in x else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
optionslist[str | MediaItem]a list of strings or items from s.media containing the options
min_optionsint | Nonethe minimum number of options to be ranked, defaults to all options
max_optionsint | Nonethe number of options to be ranked, defaults to all options
styleChoiceQuestionStylepresentation style for the options.
labelstuple[str, str]a tuple of text labels for the least and most options
randomizeboolwhether to randomize the order of the options
fixed_optionslist[str] | Nonea list of options that will not be randomized
other_optionslist[str] | Nonea list of additional options to present to the user
defaultlist[str] | Nonethe default value to use when generating test data.
skip_emptyboolif set to True, the question will be skipped if there are no options
recodesdict[str, str] | Nonea dictionary of recodes to use on this question. Generally less useful on text questions.
dont_know_optionstrOptionally add a "Don't know" option to the question using this text.
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
image_label_fieldstr | Nonethe field to use as the label for the image if using media items in the rows
show_image_labelboolwhether to show the image label or just to show the image in the rows
image_sizetuple[int, int] | Nonethe bounding box size of the images to display
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

media

@property
media: MediaCollection

Access the media collection.

The media collection contains images and videos that can be used in questions. The media are added to the survey automatically and can be uploaded from the MX8 dashboard. Additional columns added in the dashboard will be added to the media collection.

Each item in the media collection is a MediaItem object. You can access the media collection by iterating over the media object, and pass it to the image parameter of questions.

Columns can be accessed using dot notation. For example, if you have a column called "brand" in your media collection, then you can access it using media.brand. You can also get all the values of a column using the get_media_values function.

If you have not uploaded any media to the survey, then a dummy media collection will be used that contains dummy images with the following columns:

  • name
  • description
  • product
  • brand
  • campaign
  • agency
  • id

You can create your own metadata columns in the MX8 dashboard and these will be added to the media collection after you have created the survey and uploaded the media.

The columns are automatically used when reporting the results. For example, if you have a column called "brand" and you ask a question about the brand, then the results will be automatically grouped by brand.

Example

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

for media in s.media:
    s.select_question(f"What do you think of this image?",
                            options=["Like", "Dislike"],
                            image=media)

get_media_values

get_media_values(column: str) -> list[str]

Get all values of the passed metadata column from the media collection.

This is useful if you want to get all the values of a column in the media collection and use them to create questions.

Example

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

car_brands = s.get_media_values("brand")

for car in s.media:
    s.select_question("What brand is this car?",
                            options=car_brands,
                            image=car)

Parameters

NameTypeDescription
columnstrthe name of the column to get the values for.

get_image

get_image(**kwargs: Any = {}) -> MediaItem

Get the image with the specified values from the media collection.

Example

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

ford_image = s.get_image(brand="Ford")
s.image_question("What do you think of this Ford car?", image=ford_image)

s.complete()

get_video

get_video(**kwargs: Any = {}) -> MediaItem

Get the video with the specified values from the media collection.

Example

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

ford_video = s.get_video(brand="Ford")
s.play_video(video=ford_video)

s.complete()

get_images

get_images(**kwargs: Any = {}) -> list[MediaItem]

Get the images with the specified values from the media collection.

Example

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

for image in s.get_images(brand="Ford"):
    s.image_question("What do you think of this Ford car?", image=image)

s.complete()

get_videos

get_videos(**kwargs: Any = {}) -> list[MediaItem]

Get the videos with the specified values from the media collection.

Example

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

for video in s.get_videos(brand="Ford"):
    s.play_video(video=video)

s.complete()

store_value

store_value(
    name: str,
    value: str | int | bool,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> StringResponse | BoolResponse | IntResponse | ListResponse

Store a string or integer value in the survey.

Typically used to store a value calculated from a previous question.

Example

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

birth_year = s.numeric_question("What year were you born in?",
                    min_max=(1920, 2020),
                    )

s.store_value("age", birth_year - datetime.now().year)

Parameters

NameTypeDescription
namestrthe name of the value to store
valuestr | int | boolthe value to store
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

get_value

get_value(name: str) -> Any

Get a previously stored value.

Useful if you want to define survey logic based on values that you have previously stored.

Example

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

birth_year = s.numeric_question("What year were you born in?",
                    min_max=(1920, 2020),
                    )

s.store_value("age", birth_year - datetime.now().year)

s.terminate_if(s.get_value("age") < 18, "Sorry this survey is for 18+ only.")

Parameters

NameTypeDescription
namestrthe name of the value to retrieve

random

random() -> float

Return a random float between 0 and 1.

randomize

randomize(items: Sequence[Any], flatten: bool = False) -> list[Any]

Randomizes a list of items.

Typically used when iterating over a list of items that you want to ask questions about.

if you set flatten=True then items that are nested within other lists will be flattened after randomization so you can randomize a set of options but still keep some grouped together.

Example

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

car_brands = s.randomize(["Ford", "Toyota", "Honda", "Tesla"])

for brand in s.randomize(car_brands):
    s.select_question(f"What do you think of {brand} cars?",
                            options=["Like", "Dislike"])

Example with flattening

from survey import Survey

s = Survey(**globals())

genres = [
    "Jazz",
    ["Punk Rock", "Classic Rock", "Indie Rock"],  # keep this group together
    "Hip-Hop",
    ["House", "Techno"],  # keep this group together
]

all_genres = s.randomize(genres, flatten=True)

for genre in all_genres:
    s.select_question(
        f"What do you think of {genre} music?",
        options=["Like", "Dislike", "Neutral"],
    )

max_diff_question

max_diff_question(
    question: str,
    items: list[str | MediaItem] | list[list[str | MediaItem]],
    labels: list[str],
    image: MediaItem | None = None,
    randomize: bool = False,
    custom_validator: Callable[[str], str] | None = None,
    dont_know_option: str = '',
    image_label_field: str | None = None,
    show_image_label: bool = True,
    image_size: tuple[int, int] | None = None,
    tags: dict[str, Any] | None = None,
    **_kwargs: Any = {},
) -> DictResponse

Add a MaxDiff question to the survey.

This presents the user with a series of sets of items, and asks the user to select the most and least preferred items in each set.

The items are presented in a random order, and the user is asked to select the most and least preferred items in each set. The items are presented in a random order, and the user is asked to select the most and least preferred items in each set.

Example

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

car_brands = ["Ford", "Toyota", "Honda", "Tesla", "Chevrolet", "BMW", "Audi", "Mercedes"]

s.max_diff_question("Which of the following car brands do you prefer?",
                    items=car_brands,
                    labels=["Least", "Most"])

Portrait orientation

If you want to use portrait orientation, then the questions are asked multiple times, once for each label, and you must include a placholder for the labels in the question text. For example, if you have a question "Which of the following cars do you prefer?", and you want to use portrait orientation, then include a placeholder for the label in the question text, i.e., "Which of the following cars do you prefer the {label}?"

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

car_brands = ["Ford", "Toyota", "Honda", "Tesla", "Chevrolet", "BMW", "Audi", "Mercedes"]

s.max_diff_question("Which of the following cars do you prefer the **{label}**?",
                    items=car_brands,
                    labels=["Least", "Most"])

Default values

If no default value is specified, then the test data will consist of random values chosen from the options.

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

car_brands = s.multi_select_question(
    "When you think about cars, which brands immediately come to mind?",
    options=["Ford", "Toyota", "Honda", "Tesla"],
)

brand_cars = {
    "Ford": ["Fiesta", "Focus", "Mustang", "F150"],
    "Toyota": ["Corolla", "Camry", "Prius", "RAV4"],
    "Honda": ["Civic", "Accord", "CR-V", "Pilot"],
    "Tesla": ["Model S", "Model 3", "Model X", "Model Y"],
}

for brand in car_brands:
    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),
    )

Custom Errors

If you want to return a specific response to the user if they enter a specific value, you can use the custom_validator parameter. This is typically a lambda function that takes the response as a parameter and returns a string if the response is invalid.

It is typically used for "gotcha" questions, where the user is asked to enter a specific value to ensure they are paying attention.

e.g. custom_validator=lambda x: "Are you sure you meant Sleepy Cows?" if "Sleepy Cows" in x else None

Parameters

NameTypeDescription
questionstrthe question to ask the consumer
itemslist[str | MediaItem] | list[list[str | MediaItem]]a list of items to rank, or a list containing the sets of items to rank
labelslist[str]the two labels to use for the most and least preferred items
imageMediaItem | NoneAn option image to show the user, from the s.media collection
randomizeboolif set to True, the order of the items will be randomized
custom_validatorCallable[[str], str] | Nonea function to return a custom error message
dont_know_optionstrlabel to use for the don't-know option, if any.
image_label_fieldstr | Nonelabel field to use for media items in the options.
show_image_labelboolwhether to show image labels for media options.
image_sizetuple[int, int] | Nonebounding box size for the image.
tagsdict[str, Any] | NoneTags to attach to this question, from s.tags(...). You can also attach tags using the with s.tag(...): context manager.

count_validation_errors

count_validation_errors(question: str | None = None) -> int

Return the number of validation errors in the survey, or for a specific question.

Parameters

NameTypeDescription
questionstr | Noneif passed, only counts errors for this question.

authenticate_by_phone_number

authenticate_by_phone_number(
    question_1: str,
    question_2: str = 'Please enter the code we sent you.',
    termination_message: str = 'Sorry, the code you entered was incorrect',
    store_phone_number: bool = False,
    image: MediaItem | None = None,
    default_country: str | None = None,
) -> StringResponse

Authenticate the respondent by phone number.

This function asks the respondent to enter their phone number and sends a code to that number. The respondent must then enter the code to authenticate.

The response contains the phone number, if it is stored. Otherwise, it is the string "obfuscated".

You can always access the phone number by access response.phone_number on the returned object. In addition, the one time password is available as response.otp.

Example

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

s.authenticate_by_phone_number("This is a high security survey, please enter your phone number" +
                               "to continue, and we will send you a verification code.")

Parameters

NameTypeDescription
question_1strthe question to ask the consumer to enter their phone number
question_2strthe question to ask the consumer to enter the code
termination_messagestrthe message to show the user if the code is incorrect
store_phone_numberboolif set to True, the phone number will be stored in the survey data
imageMediaItem | NoneAn option image to show the user, from the s.media collection
default_countrystr | Nonethe default country code to use for the phone number

call_api

call_api(
    url: str,
    method: HttpMethod,
    data: dict | None = None,
    params: dict | None = None,
    headers: dict | None = None,
    timeout: int = 10,
) -> StringResponse

Call an external API. This is only available to call out to pre-approved domains.

:param url: The URL of the request. :param method: HTTP method ("GET" or "POST"). :param data: Data to send for POST requests. :param params: Query parameters for GET requests. :param headers: HTTP headers for the request. :param timeout: Request timeout in seconds. :return: Response object from the HTTP request. :raises ValueError: If the URL domain is not allowed.

get_all_children_age_gender

get_all_children_age_gender(
    min_age: int,
    max_age: int,
    age_recodes: dict[int, str] | None = None,
    gender_map: dict[str, str] | None = None,
    question_1_text: str | None = None,
    question_2_text: str | None = None,
    question_3_text: str | None = None,
) -> list[StringResponse]

Ask the user a series of questions to get the ages and genders of their children.

Returns a list of StringResponse objects, one for each child, with the following tags attached:

  • age: the recoded age of the child
  • gender: the gender of the child
  • name: the name of the child to present to the respondent, e.g. 16 year old son.

If the user has no children, then an empty list is returned.

The default questions are:

  1. "How many children do you have between the ages of {min_age} and {max_age}?"
  2. "For each child, please let us know their age"
  3. "Now, please let us know their gender

By default, genders are Male and Female and are mapped to son and daughter using the gender_map parameter.

Age recodes may be specified as a dictionary mapping the age to the recode value, e.g.

{
    5: "Pre-school",
    6: "Primary",
    7: "Primary",
    8: "Primary",
    9: "Primary",
    10: "Primary",
    11: "Secondary",
    12: "Secondary",
    13: "Secondary",
    14: "Secondary",
    15: "Secondary",
    16: "Secondary",
    17: "Secondary",
}

Example


from survey import Survey
s = Survey(**globals())
children = s.get_all_children_age_gender(
    min_age=5,
    max_age=18,
)
for child in children:
    s.text_question(f"What is {child.name}'s favorite subject in school?")

s.complete()

Parameters

NameTypeDescription
min_ageintthe minimum age of the children
max_ageintthe maximum age of the children
age_recodesdict[int, str] | Nonea dictionary to recode the ages
gender_mapdict[str, str] | Nonea dictionary to map genders to child terminology
question_1_textstr | Nonethe text to use for the first question
question_2_textstr | Nonethe text to use for the second question
question_3_textstr | Nonethe text to use for the third question

kid_picker_question

kid_picker_question(
    min_age: int = 13,
    max_age: int = 17,
    age_recodes: dict[int, str] | None = None,
    gender_map: dict[str, str] | None = None,
    question_1_text: str | None = None,
    question_2_text: str | None = None,
    question_3_text: str | None = None,
    question_4_text: str | None = None,
) -> StringResponse | None

Ask the user a series of questions to get the ages and genders of their children.

Then ask which child is available to take the survey now.

Returns a StringResponse object with the age and gender information.

If the user has no children, then None is returned.

The default questions are:

  1. "How many children do you have between the ages of {min_age} and {max_age}?"
  2. "For each child, please let us know their age"
  3. "Now, please let us know their gender"
  4. "Which, if any, of your children are available to take the survey now?"

By default, genders are Male and Female and the children are referred to as son and daughter using the default gender map:

{
    "Male": "son",
    "Female": "daughter"
}

Age recodes can be specified as a dictionary mapping the age to the recode value as in the get_all_children question.

Example


from survey import Survey
s = Survey(**globals())
children = s.kid_picker_question(
    min_age=5,
    max_age=18,
)
if child:
    s.show_message("Please ask your {child} to take the survey now.", child=child)
else:
    s.terminate("Sorry, this survey is for children only.")

s.complete()

Parameters

NameTypeDescription
min_ageintthe minimum age of the children
max_ageintthe maximum age of the children
age_recodesdict[int, str] | Nonea dictionary to recode the ages
gender_mapdict[str, str] | Nonea dictionary to map the genders to child terminology
question_1_textstr | Nonethe text to use for the first question
question_2_textstr | Nonethe text to use for the second question
question_3_textstr | Nonethe text to use for the third question
question_4_textstr | Nonethe text to use for the fourth question

get_exposed_values

get_exposed_values(
    source: str,
    exposed_dimension: str,
    allowed_values: list[str] | None = None,
    number_allowed_unknown_values: int = 0,
) -> ListResponse

Return a list of exposure values for a configured dimension.

The exposures must be pre-loaded into the MX8 system for this to work, please contact support for more details on how to implement this.

Example

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

products = ["SUV", "Sedan", "Coupe"]

exposed_products = s.get_exposed_values(
    source="campaign-123",
    exposed_dimension="product",
    allowed_values=products,
    number_allowed_unknown_values=1,
)

for product in products:
    s.select_question(
        f"What do you think of {product} cars?",
        options=["Like", "Dislike"],
        exposed=product in exposed_products,
    )

s.complete()

Parameters

NameTypeDescription
sourcestrthe source of the exposures, set with the server side integration, e.g. 'campaign-123'
exposed_dimensionstrthe exposure dimension to return, e.g. 'brand' or 'product'
allowed_valueslist[str] | Nonean optional list of values to filter the exposures by
number_allowed_unknown_valuesintthe number of values that are not in the allow-list that are allowed before the question is failed.

tag_exposed_media

tag_exposed_media(
    source: str,
    field_name: str,
    exposed_dimension: str = 'brand',
    number_allowed_unknown_values: int | None = None,
    number_allowed_unknown_brands: int | None = None,
) -> None

Tags media items in the survey as exposed based on IP address matching.

The exposures must be pre-loaded into the MX8 system for this to work, please contact support for more details on how to implement this.

This function tags media items in the survey as exposed based on the exposures for the current respondent. The field_name parameter is used to specify which field in the media collection to match against, and exposed_dimension selects which exposure dimension to read.

Example

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

s.tag_exposed_media(
    source="campaign-123",
    field_name="brand",
    exposed_dimension="brand",
    number_allowed_unknown_values=1,
)

for media in s.media:
    s.select_question(
        f"What do you think of this car?",
        options=["Like", "Dislike"],
        image=media,
        exposed=media.exposed,
    )
s.complete()

Parameters

NameTypeDescription
sourcestrthe source of the exposures, set with the server side integration, e.g. 'campaign-123'
field_namestrthe name of the field in the media collection to match against the exposures
exposed_dimensionstrthe exposure dimension to match against, defaults to 'brand'
number_allowed_unknown_valuesint | Nonethe number of values that are not in the allow-list that are allowed before the lookup is failed
number_allowed_unknown_brandsint | Nonedeprecated alias for number_allowed_unknown_values

insert_block

insert_block(name: str) -> None

Insert a block into the survey at the current position.

Blocks are defined in the MX8 dashboard and can be used to add custom questions to surveys without modifying the survey code.

Parameters

NameTypeDescription
namestrthe name of the block