When and Why to Use
The s.respondent property returns normalized context for the current respondent, built from metadata supplied at launch time. Use it when survey logic needs to branch on who is taking the survey — without asking an extra question. Common uses include:
- Showing country- or region-specific questions
- Adapting content for mobile respondents
- Branching on the respondent source or panel provider
- Reading provider-supplied metadata such as a panel ID
Every field you read is automatically added to your survey data as a calculated variable, so the values you branch on are also available in reporting.
Available Fields
| Field | Type | Description |
|---|---|---|
source | str | The respondent source supplied at launch time; empty string when not set |
country | str | None | Canonical MX8 Labs country code (e.g. "US"), or None when unavailable |
languages | tuple[str] | Canonical MX8 Labs language codes in preference order; empty when unavailable |
browser | str | None | Browser family parsed from the user agent (e.g. "Chrome"), or None |
device | str | None | Device family parsed from the user agent, or None |
os | str | None | Operating system family parsed from the user agent, or None |
device_type | str | None | One of "mobile", "tablet", "pc", "bot", or "other", or None when no user agent exists |
Matching Helpers
Rather than comparing raw codes yourself, use the matching helpers, which accept a code, name, or synonym (for example, "US", "USA", or "United States") and return a boolean. A value that cannot be matched returns False rather than raising an error.
| Helper | Description |
|---|---|
is_country(country) | Whether the respondent country matches the given code, name, or synonym |
is_any_country(countries) | Whether the respondent country matches any of the given values |
has_language(language) | Whether the respondent language list includes a matching language |
has_any_language(languages) | Whether any of the given languages matches the respondent language list |
get_provider_metadata(key) | A provider metadata value as a string; empty string when the key is missing |
Automatic Reporting
Reading a respondent field adds a calculated survey variable so the value is available in reporting:
- The stable reporting ID is
respondent_{field}, such asrespondent_device_type, and the question name replaces underscores with spaces, such as "Respondent device type" - Repeated access updates the same calculated element rather than creating duplicates
languagesis reported as a multi-value field; an empty value is reported as an empty multi-value. Other missing fields are reported as empty strings- Matching helpers such as
is_country(...)andhas_language(...)report the underlying field they access get_provider_metadata(...)does not automatically report provider values — uses.store_value()if you want them in your survey data
Reading respondent fields never changes launch metadata or overwrites historical stored responses.
Example Code
Branching on country and device type:
from survey import Survey
s = Survey(**globals())
if s.respondent.is_country("United States"):
s.select_question(
"Which region do you live in?",
options=["Northeast", "Midwest", "South", "West"],
tags=s.tag(country=s.respondent.country),
)
if s.respondent.device_type == "mobile":
s.show_message("Thanks for taking this on your phone.")
Reading provider metadata and storing it for reporting:
from survey import Survey
s = Survey(**globals())
panel_id = s.respondent.get_provider_metadata("panel_id")
if panel_id:
s.store_value("panel_id", panel_id)
Notes
- Values are normalized:
countryandlanguagesuse canonical MX8 Labs codes, and the browser, device, and OS fields are parsed from the respondent's user agent - Missing context is safe to read — fields return
None(or an empty string or tuple) instead of raising, so your logic should handle those cases - Because every field you read is auto-reported, prefer reading only the fields you actually use
- For values derived from respondent context (for example, a segment computed from country and device), calculate them in a normal Python variable and report them with
s.store_value()

