A friendly introduction to writing SRP surveys for export to XForm/ODK — no prior experience required.
01What Is SRP?
The Problem
You want to collect data in the field using ODK Collect, KoboToolbox, or another ODK-compatible tool. Those tools read XForm XML files — a format that is powerful but tedious to write by hand and nearly impossible to read or review at a glance.
SRP is a small, purpose-built language for writing surveys. Think of it the way you might think of Markdown
for documents — a readable, text-based syntax that describes exactly what you want, without ceremony.
You write an .srp file, and SRP exports it to a valid XForm XML file ready to load into
ODK Collect, KoboToolbox, or any other tool in the ODK ecosystem.
Here is what you can express in SRP without any programming background:
- Pages of questions with titles and introductory text
- 20 XForm-compatible question types — multiple choice, open-ended, matrix grids, ratings, sliders, media upload, and more
- Skip logic — send respondents to different questions based on their answers
- Conditional content — show or hide questions based on previous answers
- Screener logic — disqualify respondents mid-survey
The .srp file is your source of truth. The XForm XML is the output — generated, not maintained.
If your survey changes, you edit the .srp file and re-export.
It's Just a Text File
An SRP file is a plain text file with a .srp extension. You can open it in any text editor —
Notepad, VS Code, TextEdit, Vim, anything. There is nothing to install to write one.
Because it is plain text, you get a lot for free:
- Share it — email it, paste it into a chat message, put it in a shared folder
- Version it — store it in Git, see exactly what changed between drafts, collaborate with pull requests
- Copy-paste blocks — reuse a page or question block from a previous instrument in seconds
- Review it — a colleague can read the file and understand the entire survey logic at a glance, no special software needed
Convention: Files use the .srp extension by convention, but they are ordinary UTF-8 text.
Any editor that can save a plain text file will work.
Try It in Your Browser
The fastest way to get started is the SRP Playground. It has a built-in editor on the left and a live survey preview on the right. Every example in this guide can be pasted directly into the playground and previewed immediately — no account required.
Tip: As you read through this guide, open the playground in a second tab and paste in the examples. Seeing them render in real time is the fastest way to build intuition for the language before you export to XForm.
02Your First Survey
Anatomy of a Survey
Here is the smallest useful survey you can write — one page, one question, done:
page "feedback" do
title "Quick Feedback"
SingleSelect "experience" do
text "How was your experience today?"
option "Great"
option "It was okay"
option "Not good"
end
action :complete
end
Let's walk through each part:
-
page "feedback" do … end— declares a page. The name in quotes ("feedback") is a unique internal identifier. It never appears on screen; it is used when you need to refer to this page in skip logic. -
title "Quick Feedback"— the heading displayed to the respondent at the top of the page. Every page must have a title. -
SingleSelect "experience" do … end— a question block.SingleSelectis the question type (radio-button style)."experience"is the unique name for this question — used to identify it in results and in logic. -
text "…"— the question text shown to the respondent. -
option "…"— one answer choice. -
action :complete— when the respondent submits this page, mark the survey as complete. Without this, the survey would look for a next page to show.
Question names must be unique across the entire survey.
They are how SRP identifies responses and connects logic. Short, lowercase, underscore-separated names
work well: "brand_awareness", "age_range", "q3_satisfaction".
Adding More Questions
A page can hold as many questions as you like — just add them one after another inside the page block.
Respondents see all questions on the page before clicking Next.
page "about_you" do
title "A Bit About You"
SingleSelect "age_range" do
text "What is your age range?"
option "Under 25"
option "25–34"
option "35–44"
option "45–54"
option "55 or older"
end
MultiSelect "interests" do
text "Which topics interest you? Select all that apply."
min_selections 1
max_selections 3
option "Technology"
option "Health & Wellness"
option "Finance"
option "Travel"
option "Food & Cooking"
end
OpenEnded "role" do
text "What is your current job role?"
end
action :complete
end
Notice a few new things here:
MultiSelect— lets respondents pick more than one option (checkboxes).min_selections 1— require at least one choice.max_selections 3— cap it at three choices.OpenEnded— a single-line free-text input.
The required keyword makes any question mandatory — just add it inside the question block
on its own line:
OpenEnded "role" do
text "What is your current job role?"
required
end
03Pages
Structure
A survey is a sequence of pages. By default, respondents move through them in the order they appear in the file.
Each page is a page "name" do … end block with a title and any number of questions.
Rules to keep in mind:
- Page names must be unique within a survey.
- Every page must have a
title. - Pages can contain zero or more questions.
- A page with
action :completeends the survey successfully. - A page with
action :terminateends the survey and marks the respondent as disqualified. - Pages without an action simply advance to the next page in the file.
Multiple Pages
Here is a two-page survey with a welcome screen and a question page:
page "welcome" do
title "Welcome!"
Notification "intro" do
text "This short survey takes about 2 minutes. Thanks for your time."
end
end
page "questions" do
title "Your Opinion"
SingleSelect "satisfaction" do
text "How satisfied are you with our product overall?"
required
option "Very satisfied"
option "Satisfied"
option "Neutral"
option "Dissatisfied"
option "Very dissatisfied"
end
Discussion "feedback" do
text "Is there anything specific you would like us to improve?"
end
action :complete
end
Notification is a display-only block — it shows text to the respondent but collects no answer.
It is perfect for introductions, instructions, or transition messages between sections.
Discussion is a multi-line text area, great for open-ended feedback where you expect
longer responses.
04XForm-Supported Question Types
SRP has over 20 field question types, and 20 of them export to XForm. A small number of highly visual or specialized types (HeatMap, CardSort, ConjointChoice, etc.) have no XForm equivalent — they are available when running surveys on the SRP field surveys platform. The XForm Export Reference has the full compatibility table.
Text Responses
OpenEnded — single-line text → XForm string
OpenEnded "city" do
text "What city do you live in?"
required
end
Discussion — multi-line text → XForm string with appearance="multiline"
Discussion "suggestions" do
text "What improvements would you most like to see?"
end
Number — numeric input → XForm int or decimal
Use min_value / max_value to emit XForm constraints automatically.
Number "household_size" do
text "How many people live in your household?"
min_value 1
max_value 20
allow_decimals false
required
end
Selection Questions
SingleSelect — pick one → XForm select1
SingleSelect "household_water_source" do
text "What is your household's primary source of drinking water?"
required
option "Piped into home"
option "Communal standpipe"
option "Borehole or well"
option "Surface water (river, lake)"
option "Rainwater collection"
option "Tanker truck"
option "Other"
end
MultiSelect — pick many → XForm select
MultiSelect "health_conditions" do
text "Has anyone in your household been diagnosed with any of the following? Select all that apply."
option "Hypertension"
option "Diabetes"
option "Malaria"
option "Tuberculosis"
option "None of the above"
end
Ranking — drag-to-order → XForm odk:rank
Ranking "priorities" do
text "Rank these community needs from most to least urgent."
item "Clean water access"
item "Healthcare facility"
item "School or education"
item "Road infrastructure"
item "Electricity"
end
Rating & Scale Questions
Rating — star or numeric scale → XForm select1
Rating "service_quality" do
text "How would you rate the quality of service at this clinic?"
number_of_ranks 5
required
end
NPS — 0–10 fixed scale → XForm integer
NPS "recommend" do
text "How likely are you to recommend this health centre to a neighbour?"
min_label "Not at all likely"
max_label "Extremely likely"
required
end
Slider — range input → XForm range
Slider "confidence_level" do
text "How confident are you in the information you received today?"
min_value 0
max_value 100
step 5
min_label "Not at all confident"
max_label "Completely confident"
end
Matrix Questions
Matrix questions are flattened during XForm export — each row becomes its own
independent select1 or select question. The question names in the XForm
are derived from the matrix name and the row label, so keep row labels concise.
SingleSelectMatrix — one selection per row → one select1 per row
SingleSelectMatrix "service_ratings" do
text "Please rate each aspect of the clinic visit."
required
row "Waiting time"
row "Staff friendliness"
row "Cleanliness"
row "Treatment received"
column "Excellent"
column "Good"
column "Fair"
column "Poor"
end
MultiSelectMatrix — multiple selections per row → one select per row
MultiSelectMatrix "barriers" do
text "What barriers did you face when accessing each service?"
row "Antenatal care"
row "Child immunisation"
row "Family planning"
column "Distance"
column "Cost"
column "Long wait times"
column "Lack of supplies"
end
Other Supported Types
DatePicker → XForm date
DatePicker "visit_date" do
text "What was the date of your most recent clinic visit?"
required
end
Age → XForm integer
Age "respondent_age" do
text "How old are you?"
required
end
PhoneNumber → XForm string
PhoneNumber "contact_number" do
text "What is the best phone number to reach you on?"
end
Notification — display text, no input → XForm read-only note
Use Notification to show instructions or transition copy between sections.
Notification "section_intro" do
text "The next section asks about your household's access to health services. Please answer for the past 12 months."
end
Additional Supported Types
ButtonRating — button-based scale → XForm select1 (likert)
Each button becomes a <select1> item. Behaves like a Rating but with custom button labels instead of a numeric scale.
ButtonRating "ease_of_use" do
text "How easy was the registration process?"
button "Very Easy"
button "Easy"
button "Neither"
button "Difficult"
button "Very Difficult"
required
end
ButtonCheckbox — button-based multi-select → XForm select
Like MultiSelect but with a button UI. Each button maps to a <select> item.
ButtonCheckbox "services_used" do
text "Which services did you use during your visit?"
button "Outpatient"
button "Pharmacy"
button "Laboratory"
button "Maternal health"
end
ThisOrThat — binary choice → XForm select1
Presents exactly two options. Maps to a two-item <select1>.
ThisOrThat "contact_preference" do
text "How would you prefer to be contacted?"
this "By phone"
that "By text message"
end
FillInTheBlank — sentence completion → XForm string
The blank markers (___) appear as literal text in the XForm label. ODK Collect shows a text input below the full sentence.
FillInTheBlank "wait_time" do
text "I waited approximately ___ minutes before being seen."
end
MediaUpload — file capture → XForm upload
Maps to the XForm <upload> element. Use the accept attribute to specify the media type: image, audio, or video.
MediaUpload "facility_photo" do
text "Take a photo of the facility entrance sign."
accept "image"
required
end
05Skip Logic
Surveys rarely need to show everyone every question. SRP lets you route respondents to different pages based on their answers — this is called skip logic.
Skipping Pages
Add an action inside an option block to send the respondent to a specific page
when they choose that option:
page "purchase_check" do
title "About Your Purchase"
SingleSelect "made_purchase" do
text "Have you made a purchase with us in the last 90 days?"
required
option "Yes" do
action :skip_to, "purchase_details"
end
option "No" do
action :skip_to, "general_feedback"
end
end
end
page "purchase_details" do
title "Your Purchase"
Rating "purchase_satisfaction" do
text "How satisfied were you with your most recent purchase?"
number_of_ranks 5
required
end
action :complete
end
page "general_feedback" do
title "General Feedback"
Discussion "general_thoughts" do
text "What would encourage you to make a purchase?"
end
action :complete
end
When the respondent picks "Yes", they jump directly to the "purchase_details" page.
"No" takes them to "general_feedback". Pages that are skipped are simply not shown.
Note: The page name in action :skip_to, "page_name" must match
the internal name of an existing page exactly, including capitalization.
Screening Out
Use action :terminate inside an option block to end the survey and mark the respondent
as disqualified. This is the standard pattern for screener surveys:
page "screener" do
title "Eligibility Check"
SingleSelect "owns_car" do
text "Do you currently own or lease a car?"
required
option "Yes"
option "No" do
action :terminate
end
end
end
page "main_survey" do
title "About Your Vehicle"
SingleSelect "car_type" do
text "What type of vehicle do you drive?"
required
option "Sedan"
option "SUV or crossover"
option "Truck"
option "Electric or hybrid"
option "Other"
end
action :complete
end
Respondents who choose "No" are terminated immediately. Everyone else continues to the main survey.
06Segments & Conditions
Skip logic is great for simple branching, but sometimes you need more nuance — show a follow-up question only to people who rated you poorly, or ask about a feature only to people who said they use it. That is where segments come in.
What Is a Segment?
A segment is a named group that a respondent is placed into based on their answer.
You define it inside an option block using the segment keyword.
Think of it as tagging a respondent: "this person is a dissatisfied_user."
A respondent can belong to multiple segments. Segments accumulate as they move through the survey — an answer on page 2 can add them to a segment that was also used on page 1.
show_only_if
Once you have a segment, you can use show_only_if on a page or question to display it
only when the respondent is in that segment.
Passing multiple segment names to show_only_if uses OR logic —
the page or question appears if the respondent is in any of the listed segments.
A Full Example
Here is a satisfaction survey that shows a follow-up page only to dissatisfied respondents:
page "satisfaction" do
title "Overall Satisfaction"
SingleSelect "overall_sat" do
text "How satisfied are you with our service overall?"
required
option "Very satisfied"
option "Satisfied"
option "Neutral"
option "Dissatisfied" do
segment "unhappy"
end
option "Very dissatisfied" do
segment "unhappy"
end
end
end
# This page only appears for respondents in the "unhappy" segment
page "follow_up" do
title "Help Us Improve"
show_only_if "unhappy"
MultiSelect "pain_points" do
text "What areas fell short of your expectations? Select all that apply."
required
option "Response time"
option "Quality of support"
option "Value for money"
option "Ease of use"
option "Something else"
end
Discussion "improvement_details" do
text "Tell us more about what we could do better."
end
end
page "thanks" do
title "Thank You"
Notification "closing" do
text "Thank you for your feedback. We read every response and use it to improve our service."
end
action :complete
end
Satisfied and neutral respondents go straight from "satisfaction" to "thanks".
Dissatisfied respondents are placed in the "unhappy" segment and see the "follow_up" page first.
You can also use show_only_if on individual questions within a page —
not just on entire pages. This lets you keep related questions together while still
tailoring the experience:
page "feedback" do
title "Your Feedback"
SingleSelect "would_recommend" do
text "Would you recommend us to a friend?"
required
option "Yes, definitely" do
segment "promoter"
end
option "Probably yes" do
segment "promoter"
end
option "Not sure"
option "Probably not" do
segment "detractor"
end
option "Definitely not" do
segment "detractor"
end
end
# Only promoters see this question
OpenEnded "referral_reason" do
text "What would you tell a friend about us?"
show_only_if "promoter"
end
# Only detractors see this question
OpenEnded "detractor_reason" do
text "What would need to change for you to recommend us?"
show_only_if "detractor"
end
action :complete
end
07Next Steps
You now know enough to author an XForm-ready survey in SRP. Here is a quick recap:
- A survey is a sequence of
pageblocks, each with atitleand questions. - Questions have types (
SingleSelect,MultiSelect,OpenEnded, etc.), a unique name, andtext. action :skip_to, "page"inside an option routes the respondent to a different page.action :terminatedisqualifies;action :completeends successfully.segment "name"tags a respondent;show_only_if "name"conditionally shows content.- SRP files are plain text — write them anywhere, share them, version them with git.
Optional: Submission URL
When you export from the ODK Export page,
you can enter an optional Submission URL. This adds a <submission action="...">
element to the XForm, which tells ODK Collect where to send collected responses.
Leave it blank if you will configure the submission URL directly in your ODK server or tool.
Reference docs
- srpsurveys.com/playground — write and preview surveys directly in your browser, no account required.
- XForm/ODK Export Reference — the full compatibility table, type mappings, and notes on constraints and matrix flattening.
SRP is much more than XForm
XForm export covers 20 of SRP's field question types — the subset with clean ODK equivalents. The SRP language itself, and the srpsurveys.com platform built on it, go significantly further.
Syrup Field Surveys is an offline-first survey collection platform designed for research anywhere — clinics, rural communities, events, anywhere signal is unreliable. It is built around offline from the start, not as an add-on:
- Load a survey URL once. From that point on, the survey runs entirely on-device — no connectivity needed.
- Responses queue locally and sync automatically when connectivity returns. Nothing is lost.
- Clean, structured, validated data every time — no paper fallback, no manual entry.
On the full SRP platform you also get access to the complete question vocabulary — types that go well beyond what XForm can represent:
Click-coordinate capture on an image — mark locations, zones, or reactions
Drag cards into categories — ideal for mental model and taxonomy research
Best/worst scaling — find which items respondents value most and least
Discrete choice experiments — profile-based trade-off analysis
Allocate a fixed number of points across options — measure relative importance
Respondents highlight passages in a text — capture attention and sentiment
Emoji-based emotion capture — quick, culturally flexible sentiment questions
Place sticky notes on an image — spatial feedback on concepts or layouts
The platform also supports text piping ({{question_name}} substitution),
dynamic option lists populated from previous answers, and advanced skip logic.
All of it is authored in the same readable .srp format — the same language you have been learning here.
Start small. Paste the five-line example from Section 2 into the playground, add one question at a time, and preview as you go. Most people are writing real surveys within the first half hour — and exporting to XForm shortly after.