You are on page 1of 676

ODK Documentation

ODK

Aug 04, 2020


CONTENTS

1 Getting Started With ODK 3

2 ODK Collect 5

3 Setting Up ODK Collect 7

4 Using ODK Collect 35

5 Tips and Best Practices 103

6 ODK Central 165

7 Setting Up ODK Central 169

8 Using ODK Central 191

9 Intro to Forms in ODK 233

10 XLSForm 235

11 Question Types 237

12 Form Logic 343

13 Form Styling 367

14 Form Language 385

15 Form Operators and Functions 389

16 Logging enumerator behavior 415

17 Launching External Apps 425

18 Form Building Tools 429

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. i


19 Tips and Best Practices 443

20 ODK Briefcase 461

21 Setting Up ODK Briefcase 463

22 Briefcase and Aggregate 465

23 ODK Aggregate 467

24 Setting Up ODK Aggregate 469

25 Using ODK Aggregate 497

26 Tips and Best Practices 523

27 Google App Engine Support (Legacy) 525

28 Contributing to ODK Docs 531

29 OpenRosa 619

30 ODK JavaRosa 645

31 Launching ODK Collect from External Apps 647

32 Briefcase Aggregate API 651

33 Encrypted Forms 657

34 Security and Privacy 665

35 Glossary 671

ii Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


CONTENTS

ODK is a suite of open source tools that help organizations collect and manage data.
For a quick start, read Getting Started With ODK. In most cases, users of ODK:
• Create survey forms using the XLSForm standard in Excel or Google Sheets.
• Upload forms to an ODK Central server.
• Download forms into ODK Collect on an Android device.
• Use Collect to fill out forms with participants.
• Upload survey data from Collect to Central.
• Analyze or export data from Central.
This requires:
• Installing Collect on an Android device
• Installing Central on a server
While this is the recommended workflow, it is not the only way to do things. ODK is a very
flexible set of tools, and organizations will find their own best practices for adopting it.
Additional ODK tools are:
• ODK Aggregate, a proven server. We now generally recommend Central but those with
existing Aggregate servers may choose to continue using them.
• ODK Build, a drag-and-drop form designer. We generally recommend XLSForm for
its flexibility but users only building very simple forms may prefer Build.
• ODK Briefcase, a desktop tool that pulls and exports data from Aggregate and Collect.
The specifications and libraries that power the tools are:
• OpenRosa, APIs for how ODK clients communicate with ODK servers.
• ODK XForms spec, a subset of the W3C XForms specification, for use in the ODK
ecosystem.
• ODK JavaRosa, a Java library that renders forms complying with ODK XForms.
• XLSForm spec, a high-level Excel-based form specification.
• pyxform, a Python library that converts XLSForms into ODK XForms.
For a complete list of our tools, check out ODK on GitHub.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 1


CONTENTS

2 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


CHAPTER

ONE

GETTING STARTED WITH ODK

This document walks you through the recommended workflow to get started with ODK.
You will:

• Install Collect
• Install Central
• Create a form with XLSForm and upload it to Central
• Load a form into Collect from Central
• Fill out a form and upload it to Central

1.1 Install Collect

The easiest way to install the Collect app is to get it from the Google Play store.
See also:
Installing Collect

1.2 Install Central

The easiest way to set up your own Central server is to install it on DigitalOcean, a cloud
provider.
If you want to try Central out, you can request access to the sandbox.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 3


Chapter 1. Getting Started With ODK

Warning: The Central sandbox server is for evaluation purposes only. All forms and
data on this server are public and may be deleted without notice.

See also:
Installing ODK Central

1.3 Create a form with XLSForm and upload it to Central

1. Create a document in your favorite spreadsheet tool (Excel, Google Sheets, etc)
2. Design your form using XLSForm or try a sample XLSForm.
3. Upload the form to Central.

1.4 Load a form into Collect from Central

1. Find or create an App User in Central


2. Open Collect on your Android device
3. Tap Configure via QR code from the menu at the top right (� → Configure via QR
code)
4. Scan the QR code from Central
5. Go back to the app home screen and select Get Blank Form, then select your form.

1.5 Fill out a form and upload it to Central

1. Select Fill Blank Form to complete a survey.


2. Select Send Finalized Form to upload your completed survey to Central.
Now log back into Central and see your completed survey results.

4 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


CHAPTER

TWO

ODK COLLECT

ODK Collect is an open source Android app that replaces paper forms used in survey-based
data gathering. It supports a wide range of question and answer types, and is designed to
work well without network connectivity.
ODK Collect renders forms into a sequence of input prompts that apply form logic, entry
constraints, and repeating sub-structures. Users work through the prompts and can save the
submission at any point. Finalized submissions can be sent to (and new forms downloaded
from) a server.
Collect supports location, audio, images, video, barcodes, signatures, multiple-choice, free
text, and numeric answers. It can even accept answers from other apps on your device. See
a complete list of supported question types here.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 5


Chapter 2. ODK Collect

2.1 Learn more about ODK Collect

• Setting Up ODK Collect


• Using ODK Collect
• Getting Started With ODK

6 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


CHAPTER

THREE

SETTING UP ODK COLLECT

3.1 Installing Collect

3.1.1 Installing from Google Play Store (Recommended)

The ODK Collect App is available in the Google Play store.

3.1.2 Installing Manually

The Google Play store always has the latest stable release.
If you need a different version of Collect, you can download from the web and install manually.
1. From your device’s Settings, choose Security.
• Make sure Unknown Sources is checked.
• (On older versions of Android, this setting is in Applications rather than Security)
2. Open a web browser on your phone.
3. Navigate to https://github.com/getodk/collect/releases/latest and download the ODK
Collect APK.
4. In the download window, you will see ODK_Collect_vN.N.N.apk. - Select it to down-
load the file.
• On older devices, the APK will automatically install after you approve the security
settings.
• On newer devices, you must go to the download list, rename the file to restore
the .apk extension (the extension will have been renamed to .man during the
download process), then click on it to install it.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 7


Chapter 3. Setting Up ODK Collect

Note: You can also download the ODK Collect APK to your computer and load it on your
device via adb or another tool like AirDroid.

Note: On older Android devices (4.0 and earlier), ODK Collect required an external SD
Card. This is no longer an issue because Android devices have internal storage. Virtually
all current Android devices will run ODK Collect.

Tip: You can install ODK Collect on the Android emulator. This is especially helpful if
you need to project Collect onto a screen.

3.1.3 Understanding permissions

The ODK Collect application requires permissions to access device resources.


If your device runs a version of Android below 6, you will be prompted to accept all of the
permissions on app install.
If your device runs Android 6 or above, permissions will be requested as they are needed.
For example, the camera permission will only be requested the first time that you try to take
a picture. Once the permission is granted, you won’t be prompted again. If you deny the
permission, you will be asked again the next time you try to access the feature that requires
the permission unless you check ”Don’t ask me again.” If you deny the permission, you will
be shown a dialog explaining why the permission is needed.
The only permission that is required for using Collect is the storage permission and it will
be requested on first launch on Android 6+. Other permissions may or may not be needed
depending on the forms and features used. The permissions that may be requested by Collect
are:

8 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Permis- Reason
sion
Storage required for Collect to be able to access and save form data
Camera required by image and video questions to capture new media
Con- required to configure a Google account for Google Drive, Google Sheets sub-
tacts missions
Loca- required for location questions
tion
Micro- required by audio and video questions to capture new media
phone
Phone optional on form send to include deviceID in the submission and required for
forms that capture device metadata

Changing permissions from settings in Android 6+

If you are setting up Collect for someone who is not familiar with Android, you may want
to make sure all required permissions are granted in advance. To do this, open the Settings
application and tap on the Apps heading. You should now see a list of all your installed
applications. Scroll down to find ODK Collect and tap on it to see details about Collect. Tap
on the Permissions heading. You can now grant all of the permissions that will be needed.
You can also use Settings application to grant a permission after denying it or to revoke a
previously-granted permission.

3.2 Connecting to a Server

ODK Collect is used to fill forms with participants. Filled forms then need to be sent to
a central location for review and analysis. Generally, organizations do this by configuring
Collect to send forms to a server. For those working in environments without any internet
connectivity, there are other options.
When you first install Collect, it connects to a demo server. This allows you to try out the
app by downloading blank example forms, filling them out, and uploading completed forms
back to the demo server.
Once you are done trying out Collect, you will need a plan for managing forms and data
submissions. We recommend using ODK Central <central-intro> and configuring Collect
by QR code. ODK Central provides user and project management features as well as tools
for viewing and exporting data. For complex data collection projects, it is usually the right
choice. Organizations can choose to use their own infrastructure and have total control over
their server configuration. However, setting up and maintaining a server requires technical
skills.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 9


Chapter 3. Setting Up ODK Collect

Simple projects can choose to send data directly to Google Sheets.

3.2.1 Configure server from QR code

1. From the Action Button (�), select Configure via QR code

1. Position the QR code in the center of the camera field, under the red line. When the
camera focuses on the code, it will beep and scan the code.
1. Collect will apply the settings from the code and go back to the landing screen.
See also:
• Setting Up ODK Central
• Central App Users
• Configuring Collect via QR code

10 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

3.2.2 Other options

Connecting to a Google Drive Account

Warning: Spreadsheets have cell limits (currently 5 million) above which errors will be
reported.

1. From the Action Button (�), select General Settings

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 11


Chapter 3. Setting Up ODK Collect

2. Select Server

12 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

3. Select Type, and set it to Google Drive, Google Sheets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 13


Chapter 3. Setting Up ODK Collect

4. Select your Google Account. You can select any account which is already linked with
your device or add a new account as well.

14 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

5. Optional: Set a Fallback submission URL


When using Collect with a Google account, form submissions will be posted to a Google
Sheet specified in the form.
You have the option to specify a Fallback submisison URL. This is the URL of a Google
sheet to which form submissions will be posted if the submitted form does not specify
its own URL.
If your forms will specify a submission URL, you can leave this setting empty. Other-
wise, enter the URL of a Google sheet you would like to use.

Connecting to your own ODK Aggregate Server

Before you get started…


You need to install ODK Aggregate before you can connect to it.
When connecting to an ODK Aggregate server from Collect, you will need a username and
password from your Aggregate server. This can be the superuser created when you install
Aggregate, or another user account created by you.
• See Installing Aggregate to setup your ODK Aggregate server.
• See Aggregate Site Admin for details on setting up new users.

1. From the Action Button (�), select General Settings

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 15


Chapter 3. Setting Up ODK Collect

2. Select Server

16 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

3. Select Type, and set it to ODK Aggregate

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 17


Chapter 3. Setting Up ODK Collect

4. Edit ODK Aggregate settings

18 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 19


Chapter 3. Setting Up ODK Collect

Connecting to another OpenRosa server app


Any server application that implements the OpenRosa API can be connected to, using the
instructions laid out above. You would still choose ODK Aggregate as the server type.
In Server Settings, there is currently a Type option of Other. It is unlikely you will need this
option, since any server application will need to implement the same API as ODK Aggregate.
If you think you might need to connect to a non-Aggregate server application, and are having
trouble, we encourage you to visit our Support Forum.
The Other option will likely be deprecated in the future, and its use is not recommended.

Using Android Debug Bridge with Collect

Android Debug Bridge is a tool that provides command-line access to a USB-connected


Android device. It can be used to move files between the device and your computer, install
applications, and take screenshots and videos. When connected to a device that has ODK
Collect installed, it can be used to push blank form definitions and pull completed forms.

20 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Installing and setting up ADB

Android Studio

The easiest and most well-supported way to install ADB is to install Android Studio, which
includes ADB. After installing, you’ll need to enable USB Debugging.

Standalone ADB

You can also install ADB without Android studio. This is not well supported, though, and
should only be done if you cannot install Android Studio on your computer.

Managing forms with ADB

Form definitions are stored on the device in the forms subdirectory of your Collect directory.

Loading blank forms

$ adb push local/path/to/form.xml <collect-directory>/forms/form.xml

Note: The target path on the phone (the last part of the command) must include the file
name.

Deleting forms

$ adb shell rm -d <collect-directory>/forms/form.xml

Downloading forms to your computer

To download all filled records from a device:

$ adb pull <collect-directory>/instances/*

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 21


Chapter 3. Setting Up ODK Collect

Developer tasks and troubleshooting with ADB

Downloading Collect databases

Collect stores form definition and form record state information in a few SQLite databases,
which you can pull onto your local computer.
$ adb pull <collect-directory>/metadata/*.db

Taking screenshots

$ adb exec-out screencap /sdcard/image-name.png

To pull the saved image locally:


$ adb pull /sdcard/image-name.png

Note: ODK Docs contributors can use the screenshot utility script, which wraps the
adb commands and assists with saving the images to the correct location and inserting
appropriate markup in the documentation source.

Recording video

$ adb shell screenrecord /sdcard/video-name.mp4

When you hit Enter, the video starts recording immediately.


To stop the recording, press CTRL-C. If you don’t interrupt the recording, it will stop after
three minutes.
To pull the video locally:
$ adb pull /sdcard/video-name.png

Capturing logs for debugging

Capturing in-progress logs with logcat

If you are experiencing crashes or other serious glitches, and you can reproduce the bug, use
adb logcat to capture log events during the crash.

22 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

1. Before reproducing the bug, begin piping logs to a file:

adb logcat > logfile.txt

This will write all logged errors to your local file logfile.txt as they occur.
2. Reproduce the bug or crash event.
3. Type CTRL-C to stop logging.
You can then upload the logfile.txt file to a a support forum post or post in the ODK
Forum.

Pull a bug report

If more in-depth information is needed, you can pull a complete bug report from the device.

adb bugreport

This copies a ZIP file locally containing all system messages, error logs, and diagnostic
output, along with information about the device’s hardware, firmware, and operating system.
See also:
https://developer.android.com/studio/debug/bug-report.html

Identifying the Collect directory on your device

The ODK Collect directory on your device is:


• /sdcard/odk if you are running an ODK Collect version less than v1.26.0 or have a
file migration banner on the main screen
• /sdcard/Android/data/org.odk.collect.android/files if you have ODK Collect
version v1.26.0+ and don’t have a file migration banner on the main screen
Prior to ODK Collect v1.26.0, all Collect files were stored in the /sdcard/odk directory.
This directory was available to other applications to integrate with which can be very useful
but can pose privacy risks.
Starting August 2020, Google will no longer allow Android applications to read or write files
directly to this folder. Instead, each application will only be able to write files to a special
directory that only it has access to. You can read more about this change on the forum.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 23


Chapter 3. Setting Up ODK Collect

Using ODK Briefcase

Pulling forms

To pull blank forms and submissions:


1. Open the Pull tab.
2. Select a pull source option from the Pull from drop-down, and click on the Configure
button. Fill in any information needed to use the selected source.
See more on the various sources below.
3. Select the forms you want to pull and click Pull.

You can see the details of the operation by clicking on the button.
4. You can cancel an ongoing pull operation at any point by clicking Cancel.

Central server

Briefcase will ask for the following information when choosing a Central server as the pull
source:
• A URL
• A Project ID number
• An Email address
• A Password

Warning: The Start pull from last submission pulled setting will have no effect while
pulling forms from a Central server.

Aggregate server

Briefcase will ask for the following information when setting an Aggregate server as the pull
source:
• A URL
• A Username (optional)
• A Password (optional)

24 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Collect directory

Briefcase will ask for the directory on your computer where you have placed Collect’s /odk
directory. We recommend following these steps to get a copy of Collect’s /odk directory into
your computer:
1. Ensure all filled-in forms are finalized.
If you have incomplete forms that you cannot finalize before pulling into
Briefcase, delete them. If you need to keep them, make a copy of your
Collect directory before deleting them, and restore it after you are finished.
2. Using your device, create a zip archive of your Collect directory with a file managing
app such as OI File Manager.
3. Transfer the zip file to your local hard drive via a USB cable. You can also use the
Share feature in your file manager to transfer it to a third-party service like Google
Drive then download it to your local hard drive.
4. Once the zip file is on your local hard drive, unzip the file.

Warning: When pulling from Collect, Briefcase pulls incomplete, saved, or finalized
forms. After you pull forms into Briefcase, it is important that you delete them from
Collect. Otherwise, the next time you pull, you will create duplicates.

Tip: If you have Android developer tools installed, another option is to use the Android
Debug Bridge to pull filled forms:

$ adb pull <collect-directory>/instances

Form definition

Briefcase will ask for the location of the blank form definition in your computer.

Tip: This enables a workflow to upload blank form definitions with many media attach-
ments to Aggregate:
1. Pull the form using the Pull from option.
2. Push the form to your Aggregate server.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 25


Chapter 3. Setting Up ODK Collect

Warning: Ensure that all attached media is available relative to the form definition
file location.

Pushing forms

To push blank forms and submissions:


1. Open the Push tab.
2. Select a push target option from the Push to drop-down, and click on the Configure
button. Fill in any information needed to use the selected source.
See more on the various targets below.
3. Select the forms you want to push and click Push.

You can see the details of the operation by clicking on the button.
4. You can cancel an ongoing push operation at any point by clicking Cancel.

Central server

Briefcase will ask for the following information when using a Central server as the push
target:
• A URL
• A Project ID number
• An Email address
• A Password

Warning: Pushing forms and submissions to Central currently has the following limi-
tations:
• Central will reject files that might have already been pushed before, even if they’re
different the second time.
• Central will reject submissions belonging to a form version that it doesn’t know
about.

26 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Aggregate server

Briefcase will ask for the following information when using an Aggregate server as the push
source:
• A URL
• A Username (optional)
• A Password (optional)

Pull and push settings

The settings for push and pull can be configured in the Settings tab:
• You can set a number of Maximum simultaneous HTTP connections. This can be
increased to speed-up big pull operations or decreased to prevent saturating server
bandwidth.
• You can enable Start pull from last submission pulled to save time and bandwidth by
not pulling from the first submission.
– This is only available for Aggregate servers at this moment and only benefits
forms with more than 100 submissions.
– You can clear the pull history and pull every submission by clicking on Clear pull
history.
• You can enable Remember passwords (unencrypted). This will enable a couple of
features:
– Briefcase will remember the pull sources and push targets you configure when
they require user credentials. As a result, you won’t need to configure them when
launching Briefcase again.
– Briefcase will let you enable the Pull before export option when exporting forms.
• You can enable Use HTTP proxy to route your HTTP requests through a proxy host.
You will have to provide the proxy’s Host (IP address or hostname), and the Port
number.

Export forms to CSV

1. Open the Export tab.


2. Click on the Set Default Configuration button.
• Set an Export directory.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 27


Chapter 3. Setting Up ODK Collect

• If exporting Encrypted Forms, set the corresponding PEM file location. See the En-
crypted forms section for more information.
• If you wish, select a Start date and an End date to specify a limited date range to
export.
• Toggle export parameters as needed:
– Export media files enables exporting media files into the chosen export directory
– Overwrite existing files enables overwriting form submission data in the output
files. The default behavior is to append data.
– Split select multiples enables splitting select multiple fields. Enabling this setting
will create an extra output column per select choice, with a 1 if the choice was
selected, or 0 otherwise. This only affects select fields without a choice filter and
that are not from an external file (including widgets with search appearance).
– Include GeoJSON enables generating a GeoJSON file with spatial data from all
exported submissions.
– Remove group names enables removing non-repeat group names from column
names in the CSV.
– Pull before export enables trying to pull the selected forms in case there are new
form submissions to be exported.
1. Select the forms to export.
If you are selecting and exporting more than one form, you may need to set individual
export settings. To do this, click the gear icon (�) next to the form name.
2. Click Export.

Tip: To import CSVs into Excel, you cannot download and open in one step; nor can you
double-click on the CSV. You must open Excel and choose Import. If you are asked, the file
origin or encoding is UTF-8.

Output files

Briefcase will generate a different number of files and directories depending on the form’s
contents and the export configuration selected by the user. This can include, per form:
• One main CSV file. For example: Form Name.csv
• If the form includes any repeat group, one CSV file for each one of them. For example:
Form Name-repeat group name.csv

28 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

• If any submission includes binary attachments, they are copied to a media directory,
relative to the export directory. For example: media/1538040007350.jpg
• If the user enables the Include GeoJSON export configuration option, one GeoJSON
file with spatial data. For example: Form Name.geojson
• If the form includes audit metadata:
– One CSV file with audit data from all submissions. For example: Form Name -
audit.csv
– One CSV audit file for each exported submission in the media directory, relative
to the export directory. For example: media/audit-uuid56880d5e-ee8a-4832-b69d-
6dfdd526e2dc.csv

Table 3.1: Summary Table


Output file How many? Conditions Path Example
Main CSV One ./ Form Name.csv
Repeat One per repeat ./ Form Name-repeat group
CSV group name.csv
Binary at- As many as there ./me- media/1538040007350.jpg
tachment are in submissions dia
GeoJSON One The user enables In- ./ Form Name.geojson
clude GeoJSON ex-
port
Audit One The form includes ./ Form Name - audit.csv
CSV audit metadata
Individual One per submis- The form includes ./me- audit-uuid56880d5e-
audit CSV sion audit metadata dia ee8a-4832-b69d-
6dfdd526e2dc.csv

There’s more information available about the CSV file content structure and filename pat-
terns in the export format documentation.

Working with the command line

Briefcase has a command line interface (CLI) to enable scripting of many of the actions that
can be taken in the graphical user interface (GUI).
New in version 1.4.4: A CLI was added.
New in version 1.9.0: The CLI first takes an operation parameter and then modifiers to that
operation

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 29


Chapter 3. Setting Up ODK Collect

Getting CLI help

To get help about the command line operation:

$ java -jar {path/to/briefcase-jar-file} --help

Pulling forms from Aggregate

• CLI flag: -plla or –pull_aggregate


• Usage:

$ java -jar {path/to/briefcase-jar-file} --pull_aggregate --storage_


,→directory {path/to/briefcase-storage-location} --aggregate_url {aggregate-

,→url} --odk_username {username} --odk_password {password}

• Help section:

Params for -plla operation:


-p,--odk_password <arg> ODK Password
-sd,--storage_directory <arg> Briefcase storage directory
-u,--odk_username <arg> ODK Username
-url,--aggregate_url <arg> Aggregate server URL
Optional params for -plla operation:
-id,--form_id <arg> Form ID
-ii,--include_incomplete Include incomplete submissions
-mhc,--max_http_connections <arg> Maximum simultaneous HTTP␣
,→connections (defaults to 8)

-sfd,--start_from_date <arg> Start pull from date


-sfl,--start_from_last Start pull from last submission␣
,→pulled

Warning: This CLI operation will pull all forms Briefcase has permissions to if no
-id parameter is defined.

Pulling forms from Collect

This command assumes you have already copied and unzipped the odk file as described here.
• CLI flag: -pc or –pull_collect
• Usage:

30 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

$ java -jar {path/to/briefcase-jar-file} --pull_collect --storage_directory


,→{path/to/briefcase-storage-location} --odk_directory {path/to/unzipped-

,→odk-file}

• Help section:

Params for -pc operation:


-od,--odk_directory <arg> ODK directory
-sd,--storage_directory <arg> Briefcase storage directory
Optional params for -pc operation:
-id,--form_id <arg> Form ID

Warning: This CLI operation will pull all forms present on the odk directory if no
-id parameter is defined.

Pushing forms to Aggregate

• CLI flag: -psha or –push_aggregate


• Usage:

$ java -jar {path/to/briefcase-jar-file} --push_aggregate --form_id {form-


,→id} --storage_directory {path/to/briefcase-storage-location} --aggregate_

,→url {aggregate-url} --odk_username {username} --odk_password {password}

• Help section:

Params for -psha operation:


-id,--form_id <arg> Form ID
-p,--odk_password <arg> ODK Password
-sd,--storage_directory <arg> Briefcase storage directory
-u,--odk_username <arg> ODK Username
-url,--aggregate_url <arg> Aggregate server URL
Optional params for -psha operation:
-fsb,--force_send_blank Force sending the blank form to the␣
,→Aggregate instance

-mhc,--max_http_connections <arg> Maximum simultaneous HTTP␣


,→connections (defaults to 8)

Warning: This CLI operation will only update the blank form if it does not already
exist, whereas the GUI will always update the form.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 31


Chapter 3. Setting Up ODK Collect

Exporting forms to CSV

• CLI flag: -e or –export


• Usage:

$ java -jar {path/to/briefcase-jar-file} --export --form_id {form-id} --


,→storage_directory {path/to/briefcase-storage-location} --export_directory

,→{path/to/output-directory} --export_filename {output-file-name.csv}

• Help section:

Params for -e operation:


-ed,--export_directory <arg> Export directory
-f,--export_filename <arg> Filename for export operation
-id,--form_id <arg> Form ID
-sd,--storage_directory <arg> Briefcase storage directory
Optional params for -e operation:
-em,--exclude_media_export Exclude media in export
-end,--export_end_date <arg> Export end date (inclusive) (yyyy-MM-
,→dd or yyyy/MM/dd)

-ig,--include_geojson Include a GeoJSON file with spatial␣


,→data

-oc,--overwrite_csv_export Overwrite files during export


-pb,--pull_before Pull before export
-pf,--pem_file <arg> PEM file for form decryption
-rgn,--remove_group_names Remove group names from column names
-ssm,--split_select_multiples Split select multiple fields
-start,--export_start_date <arg> Export start date (inclusive) (yyyy-
,→MM-dd or yyyy/MM/dd)

Clear saved preferences

• CLI flag: -c or –clear_prefs


• Usage:

$ java -jar {path/to/briefcase-jar-file} --clear_prefs

Briefcase log files

Briefcase creates a log file with warnings and errors that might be useful for troubleshooting.

32 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


3.2. Connecting to a Server

Default log file location

If something goes wrong while using Briefcase and you look for help, it’s possible that you’re
asked to provide your log file.
The default location for the log file is the directory where you are when launching Briefcase,
and the default filename is ”briefcase.log”
Briefcase will create the log file on launch if it doesn’t previously exist. Otherwise, it will
append lines at the end of a pre-existing log file.

How to use a custom log configuration

Optionally, you can use a custom log configuration file to override the default log settings
on Briefcase.
First, you need to create a ”logback.xml” file somewhere in your computer to contain your
custom log configuration. This is a sample configuration file you can use as a template:

<configuration>
<appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.
,→RollingFileAppender">

<file>briefcase.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>briefcase.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="ROLLINGFILE" />
</root>
</configuration>

Check the full syntax of Logback configuration files here.

You can set all sorts of new log configurations to adapt Briefcase to your needs:
• Set a fixed log file location
• Fine tune the log’s verbosity by setting a different log level
• Silence specific log lines while keeping others

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 33


Chapter 3. Setting Up ODK Collect

• Set a custom log format (see the Encoders chapter)


• Set custom appenders, to define a file rolling policy (daily, by log file size,
for example), for example (see the Appenders chapter)

Once you have your configuration file ready, you can use it by adding a -Dlogging.config
argument when launching Briefcase:

$ java -Dlogging.config="{path/to/logback.xml}" -jar {path/to/briefcase-jar-file}

3.3 Configuring ODK Collect

ODK Collect is intended to be a flexible tool that can support many different types of
data collection workflows. For many organizations, the only configuration needed will be
connecting to a server. However, there are many cases where additional configuration is
helpful. Collect Menus, Settings, and Security describes all of the settings available in the
application.
To configure multiple devices, we recommend generating a QR code with settings from one
device or an external application as described in Configuring Collect via QR code and then
scanning that code from the devices that need to be configured. Starting in ODK Collect
v1.26.0, there is quick access to scan a settings QR code from the main screen:

34 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


CHAPTER

FOUR

USING ODK COLLECT

This is an in-depth guide to using the Collect App


To learn about the main features and try out ODK, see the Getting Started Guide for a quick
walk-through.

ODK Collect is used by enumerators to collect survey data by filling out forms with partic-
ipants.
To use ODK Collect:
1. Get blank forms from ODK Aggregate Server or Google Drive
2. Fill out surveys with participants
3. Upload completed surveys to Aggregate or Google Drive

ODK Collect User Guide

4.1 Managing Forms in Collect

See also:
For an overview on forms and form design, see Intro to Forms in ODK.

4.1.1 Loading Blank Forms

A blank form is a .xml file containing a form definition consistent with the XForm specifica-
tion. Blank forms can be created using ODK Build or XLSForm.
In order to fill out forms with survey participants, you must first load blank forms into the
Collect App.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 35


Chapter 4. Using ODK Collect

Loading Forms from a server

If you have connected ODK Collect to a server or Google Drive Account:


1. Select Get blank forms on the app home screen to browse available forms and download
them to your device.

2. Find and download forms.


• If you are using a server, you will see a list of available forms. Select the ones you
would like download, and tap Get Selected.

36 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

Note: Before downloading blank forms from your server to Collect, a form
has to be uploaded. See Form Management in ODK Central.

• If you are using Google Drive, the Get Blank Form screen will display the folders
in your Google Drive account and any XML documents. Select and download the
forms you want.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 37


Chapter 4. Using ODK Collect

Warning: All XML documents in Google Drive will appear in Collect. XML
documents will be listed even if they are not valid XForms.

38 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

And you can actually download any XML document, even if it isn’t a real
XForm.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 39


Chapter 4. Using ODK Collect

But you can’t Fill Out a non-form.

40 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

Loading forms directly

Loading forms with adb

You can load forms directly from a computer to your device’s Collect directory via USB,
using Android Debug Bridge.

$ adb push path/to/form.xml <collect-directory>/forms/form.xml

Loading forms from device storage

You can also download forms to your device via a web browser, and move them to the forms/
directory, using the device’s file manager (Settings -> Storage & USB -> Explore).
1. Go to the Settings menu (�) on your device and find Storage & USB
2. From the internal storage screen, select Explore to open the file manager.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 41


Chapter 4. Using ODK Collect

Fig. 4.1: The settings menu may look different on your device.

42 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

Fig. 4.2: The Explore option opens a file manager that you can use to move forms into
Collect.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 43


Chapter 4. Using ODK Collect

Loading form media

If a form includes images or other media, those files have to be loaded to the device along
with the form.
Media files must be placed in a folder labeled form-name-media.
• When using ODK Central, first upload your form definition. Central will then prompt
you to add media files if necessary. The files are downloaded automatically when
fetching blank forms.
• When using Google Drive, the -media folder should be uploaded to the same location
as the form. If you share forms with another user, you need to share the parent folder
which contains a form and a folder with media files. Sharing both of them separately
wouldn’t be enough.
• If loading forms directly to your device, the -media folder needs to be placed in the
forms subdirectory of your Collect directory, alongside the form itself.

4.1.2 Editing Saved Forms

Completed (filled-in) form instances can be edited after they have been saved.
1. Select Edit Saved Form

44 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

2. Select a form by name

This will reopen the form instance, which you are then free to edit. Form instances are listed
by name, which is one reason it can be helpful to name the form instance after filling it out.

Note:
• Sent forms will not appear in the Edit Saved Forms list.
• Sent forms, will be available for viewing in View Sent Forms list, along with the details
which cannot be edited.
• You may freely edit Saved and Finalized forms.

4.1.3 Transferring Finalized Forms

To perform analysis on data collected with the Collect app, you will need to get the filled
forms off of the devices. Generally, this is done by uploading them to an ODK server or
Google Sheets. To do this, you will first need to configure a server.
In some cases, you may want to pull filled forms directly from a device. This can be simpler
than setting up a server if you are only using a small number of devices or when there is no
Internet access. It can also be helpful to recover from submission failures.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 45


Chapter 4. Using ODK Collect

Sending Finalized Forms to a Server

If you are connected to a server or Google Drive Account, use Send Finalized Forms to
upload Finalized form instances.
Uploading a filled form from within the Collect app marks that form as sent. Sent forms are
no longer editable, but they remain viewable until they are deleted.

Note: Blank values in the form are sent to google sheets as cells with a space and not as
empty cells. When you are testing for empty cells, you might not get the correct results. To
make sure you get the correct results, you could:
• Use the TRIM function in the google sheets to remove the leading and trailing spaces
from the cells.
• Define empty cell in your tests to be a cell that is either empty or contains a single
space.
Values from questions: text, select_multiple and barcode will be preceded by an apostrophe.
This prevents Google Sheets from guessing at the data type and applying a format that may
not be appropriate (e.g. making 1940 10 5 into a date when it actually is the value of a select
multiple). Raw values may be used in any kind of computation and the apostrophes only
are visible when editing a value. You may choose to manually apply a format for certain

46 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

columns if desired.

Note: Using Google Drive as a server, filled forms are sent to the first sheet in a given
spreadsheet, no matter what its name is. If you use one spreadsheet to keep a form definition
and to collect filled forms make sure the sheet you expect to be filled is in the first place.

Sending Previously-Sent Forms

If you can’t find a submission that you expect on your server or need to re-send a submission
for other reasons, you can change the view of the Send Finalized Forms screen to show both
sent and unsent forms.
To show sent and unsent forms: � → Change View → Show Sent and Unsent Forms

Pulling Forms into Briefcase

ODK Briefcase is a desktop application that can be used to pull filled forms to your local
computer. You will first need to transfer the filled forms to your computer. This will not
update the state of the form to Sent.

4.1.4 Deleting Forms

You can delete Blank forms as well as filled forms in any state (Saved, Finalized, or Sent).
Deleting Blank forms or filled forms in Saved or Finalized state removes every trace of that
form definition or filled form. Deleting a Sent form deletes the form contents but metadata
associated with it including the deletion date and the instance name are maintained for
display in the View Sent Form list.
1. Select Delete Saved Form on the app home screen.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 47


Chapter 4. Using ODK Collect

2. Select the Saved Forms or Blank Forms tab.

Note: Deleted Forms are listed in the View Sent Forms page, but cannot be viewed. They
are indicated with the crossed-out eye icon.

48 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.1. Managing Forms in Collect

Fig. 4.3: The Saved Forms tab lists form instances that are saved, finalized, or sent.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 49


Chapter 4. Using ODK Collect

Fig. 4.4: The Blank Forms tab lists blank forms.

50 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

Deleting Forms with adb

You can also delete form instances directly with Android Debug Bridge. They are stored in
the instances subdirectory of your Collect directory, with a directory for each instance.

4.2 Filling out Forms with Collect

ODK Collect is used by enumerators to complete survey forms with participants.

Before you get started…


Before you can fill out a form, you need to load at least one form into Collect.

1. Select Fill Blank Form from the Main Menu

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 51


Chapter 4. Using ODK Collect

2. Select a form to fill out from the form list

52 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

3. Once you have completed the form, prepare it for upload by finalizing it.

4.2.1 Answering questions

Free response

Free-entry text and number answers are entered using the device keyboard. The appropriate
keyboard (letters or numbers) opens when the question appears.
Video showing text keyboard popup when a string input is required and number keyboard
popup when a number input is required.

Select response

Questions with response choices can be answered by touching the selected items. These
include radio buttons (single-select), dropdowns (single-select), check boxes (multi-select),
and image choices (single and multi-select).

Fig. 4.5: Radio buttons accept one selection.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 53


Chapter 4. Using ODK Collect

Fig. 4.6: Check boxes accept multiple answers.

54 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

Fig. 4.7: Select images by touching them.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 55


Chapter 4. Using ODK Collect

Capture answer from device

Many question formats launch additional features, form widgets, or apps to collect an answer.
This includes audio and video recording, signature collection, photo capture, date and time
widgets, location widgets, and barcodes.
In all cases, buttons below the question text will guide you through providing the response.

56 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 57


Chapter 4. Using ODK Collect

See also:
For a (mostly) complete guide to form question appearance, see Question Types.

4.2.2 Removing answers

To remove a response, Long Press on the question label.

58 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

4.2.3 Adding instances of repeats

If you have a repeating group, you can add new instances of that repeat in the following
ways:
1. By navigating into an empty repeat, or to the next question at the very end of the
repeat, you will automatically be prompted to add a new instance of that repeat.
2. By clicking the ”add” button in the jump menu:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 59


Chapter 4. Using ODK Collect

4.2.4 Removing instances of repeats

If you have a repeating group, you can remove existing instances of that repeat in the
following ways:
1. By long pressing on the question label in the same way as for removing answers
2. By clicking the ”remove” button in the jump menu:

60 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

4.2.5 Navigating the form

Swipe

To move between questions, Swipe Left or Right.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 61


Chapter 4. Using ODK Collect

Video showing swiping between three questions.

Left and Right Buttons

If you prefer Forward and Back buttons for navigation, you can switch to that in � -> General
Settings -> User Interface.
1. Open the Action Menu (�)

62 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

2. Select General Settings.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 63


Chapter 4. Using ODK Collect

3. Select User Interface

4. Select Navigation

64 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

5. Update your form navigation preference

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 65


Chapter 4. Using ODK Collect

Jumping to questions

The arrow icon ( ) in the top right corner opens the jump menu. From the jump
menu, you can go to any question or go to the beginning/ending of the form.

66 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

If you’re inside of a group of questions, you can navigate ”up” in the hierarchy using the ”go
up” button:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 67


Chapter 4. Using ODK Collect

The jump menu also provides shortcuts to add or remove instances of repeating groups.

Note: If a form contains questions in a repeats, those questions will only appear in the
Jump menu once an actual record is created.

Autoadvance Questions

Some questions will automatically advance to the next question after being answered.
Video showing auto-advance after the questions are answered.

Required Questions

Required questions will not allow you to advance unless answered.

68 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

4.2.6 Changing language of a form

If a form is available in multiple languages, you can choose a language in which you want
the questions to appear.
1. Open the Action Menu (�)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 69


Chapter 4. Using ODK Collect

2. Select Change Language.

70 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

Note: Change Language option is only visible if a form is available in more than one
language.

3. Select the language you want the form questions to appear in.

4.2.7 Saving a partially filled form

If you wish to save a partially filled form, you can click on the save icon ( ) beside
the form name.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 71


Chapter 4. Using ODK Collect

To edit the saved form, select Edit Saved Form in the Main Menu and select the form you
wish to edit.

4.2.8 Completing a Form

Once you have reached the end of a form, you will have the opportunity to Save and Exit
the form.

72 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

At this point, you may also:

Name the form

The last form screen provides a default name for the form (defined by the form designer).
You can rename it. This name only applies to that particular instance of a completed form
(not to the blank form).

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 73


Chapter 4. Using ODK Collect

The Form Name identifies the form in lists throughout the app. For this reason, a meaningful
name may be important to you. After you’ve saved the name, the form automatically moves
to the Send Finalized Form section, from where you can send it.

74 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.2. Filling out Forms with Collect

Mark the form as Finalized

Only Finalized forms can be uploaded to a server.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 75


Chapter 4. Using ODK Collect

4.3 Collect Menus, Settings, and Security

4.3.1 Main Menu

Fill Blank Form Lists available blank forms and lets you select a form to begin filling
out.
Edit Saved Form Lists completed and saved forms and lets you select a form to edit.
Send Finalized Form Lists finalized but unsent forms and lets you select forms to send
to the server.
View Sent Form Lists forms that have been sent, even if they were deleted.
Get Blank form Lists blank forms available on the server and lets you download them.
Delete Saved Form Lists all the Saved and Blank Forms and lets you delete them.

4.3.2 General Settings

To access General Settings: � → General Settings

76 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Server Settings

Server settings configure the connection to an OpenRosa server (Central, etc) or a Google
Drive account.
To access Server Settings: � → General Settings → Server

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 77


Chapter 4. Using ODK Collect

See also:
Connecting to a Server

User Interface Settings

User Interface settings control Collect’s appearance and behavior.


To access User Interface settings: � → General Settings → User Interface

78 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Theme

Toggles Light and Dark themes.


New in version 1.15.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 79


Chapter 4. Using ODK Collect

80 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Language

Forces the Collect interface to use a specific language. By default, Collect matches
the device language. Note that this only sets the language for the Collect interface
and not for form contents. For multi-language forms, the form language is set
while filling out that form. The Collect translations are provided by the ODK
community through the Transifex service. You can join Transifex to add or
correct translations in your language.

Text font size

Sets the size of fonts used in the form-filling interface.

Navigation

Sets form navigation style for moving between questions.


Options:
• Horizontal swiping
• Forward and back buttons
• Both

Splash Screen

Sets an image to display while Collect loads.

Maps Settings

Maps settings configure the maps shown by the location question types.
To access Maps settings: � → General Settings → Maps

Note: Prior to ODK Collect v1.23, map settings were available in the User Interface
Settings. The basemap was configured by first selecting a Mapping SDK and then a Basemap.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 81


Chapter 4. Using ODK Collect

Basemap settings

Basemap settings configure the background of maps shown by the location question types.
Basemaps are provided by several different Sources which may each make several different
map Styles available. A basemap is intended to provide details that help users orient a map
and to make the map easy to use in a particular data collection environment. For example,
if the data to be collected relates to elevation, consider selecting a topographic basemap.
Sources A basemap source provides one or more map styles:
• Google basemap styles are used by Google Maps and other Google products.
• Mapbox basemap styles are used in many familiar products.
• OpenStreetMap provides one style which also powers openstreetmap.org. Open-
StreetMap data is used in basemaps provided by all other sources as well.
• USGS is the United States Geological Survey. It provides topograpic and satellite
basemaps for the United States only.
• Stamen provides a terrain basemap with large labels.
• Carto basemap styles are designed to be used with data layers.

Reference layer settings

Reference layer settings configure map data shown on top of the basemap. Currently, a
reference layer can only be defined by an offline MBTiles file as described in Using Offline
Maps. The reference layer will appear when the zoom level is within the range supported
by the file. If a reference layer has no transparency, it will fully cover the basemap selected
above and behave like an offline basemap. Vector MBTiles files will only be available in the
Layer data file menu if a Mapbox basemap is selected. Raster MBTiles files will be available
for any basemap source and style.

Form Management Settings

Form Management settings control default behavior when editing, finalizing, and importing
forms.
To access Form Management settings: � → General Settings → Form Management

82 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 83


Chapter 4. Using ODK Collect

Form update

Periodic form updates check

Specifies the frequency at which the configured server should be polled for updates
to the forms on the device. The user will receive a notification when one or more
forms has an update available to its form definition or media files. Tapping on
the notification will go to Get Blank Form where the user can choose to download
some or all of the updated forms.

Automatic download

Only available if Periodic form updates check is set. When Automatic download
is enabled, the periodic form update check will trigger an automatic download of
any forms on the device that have an update to their form definition or media
files. The user will receive a notification when the automatic download completes
with either a success or failure. Tapping on the notification will go to Get Blank
Form where the user will see success or failure messages for each form for which
an update was attempted.

Hide old form versions

When enabled, if there are multiple versions of the same form, only the most
recently downloaded will be displayed on the Fill Blank Form screen.

Form submission

Auto send

When enabled, forms are sent immediately when they are finalized, if the device
can connect to the internet. If an internet connection is not available at the time
of finalization, your finalized forms will be queued to send as soon as connectivity
is established. You can specify whether to send over WiFi, cellular data, or both.

Delete after send

When enabled, form instances are deleted once they are sent.

84 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Form filling

Default to finalized

When enabled, records are set to be finalized when saved at the end of a form-
filling session. You can opt out of this at the end of filling any specific record.
This is particularly important to consider when using encrypted forms because
encryption happens on finalization. Finalized records for encrypted forms can’t
be opened because they are encrypted. Records for encrypted forms that have
not been finalized are not encrypted and can be edited.

Constraint processing

Sets when form responses are validated against constraints.


Options:
• Upon forward swipe. (That is, right after the question is answered.)
• At finalization.

High res video

When enabled, Video widgets widgets will record high resolution video if possible.

Image size

New in version 1.11.0.


Sets the default maximum size for images added to forms, as measured by the
number of pixels on the longest edge. Images larger than the maximum are scaled
down immediately after being added.
Options:
Original size from camera (default) Images are unchanged when added to
a form. Recommended for use only when images must contain a lot of detail
and when the internet connection used to send submissions is fast.
Very small (640px) Recommended when images don’t need to be detailed or
the internet connection used to send submissions is slow.
Small (1024px) Sufficiently detailed for most on-screen viewing but too small
for printing.
Medium (2048px) Sufficiently detailed for most uses, including printing.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 85


Chapter 4. Using ODK Collect

Large (3072px) Recommended when a lot of detail is needed, but you want
to reduce the size of image files as much as possible.

Show guidance for questions

Guidance hints on questions can be used to display additional information that


is not always needed. For example, they can be used to show extra instructions
to be used during training or valuable only on a printout. If set to Yes - always
shown, guidance hints will always be displayed below regular hints. If set to Yes
- collapsed, the user will need to tap to view guidance hints.

Form import

Finalize forms on import

When enabled, forms added directly to the instances/ directory are automati-
cally set to Finalized. This is particularly relevant when putting records for an
encrypted form directly to the device because encryption happens on finalization.

User and Device Identity Settings

User and device identity settings control how personally identifiable information and device
ID are used.
To access User and device identity settings: � → General Settings → User and device
identity

86 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Form metadata settings

Form metadata settings control identifying information added to forms filled on the device.
To access form metadata settings: � → General Settings → User and Device Identity
→ Form Metadata

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 87


Chapter 4. Using ODK Collect

User-defined

You can edit the following:


• Username
• Phone number
• Email address

Note:
• If no username is set here, the username from Server settings is used instead.
• You can restrict editing of the username in admin settings.

Device-defined

You cannot edit these:


• Device ID
• Subscriber ID

88 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

• SIM serial number


• Install ID
Device ID is currently set to the device IMEI. Starting in August 2020, Google will no
longer allow Android applications to read the IMEI. At that time, the Collect-generated
Install ID will be used as the Device ID. Both are currently displayed to allow organizations
to transition over. Install ID can be copied by long-pressing on its text.

Usage data

When enabled, ODK Collect sends anonymous usage and error data back to the ODK
development team, which helps us improve the application.

4.3.3 Admin Settings

Admin settings manage other settings and features, letting you import or export settings,
reset settings and delete cached data, and restrict which features are available to users of the
app.
Admin settings are useful when you are managing devices that will be used by many enu-
merators, and you would like to limit the options available to those enumerators.
You can password protect the Admin setting screen, so enumerators cannot adjust settings
or access restricted features.
To access Admin settings: � → Admin Settings

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 89


Chapter 4. Using ODK Collect

General Settings Provides access to General Settings, with all items unrestricted.
Admin Password Lets you password protect this screen.
Reset application Lets you reset to default settings, delete forms, and empty caches.
Import/Export settings See:

90 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Configuring Collect via QR code

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 91


Chapter 4. Using ODK Collect

Settings QR codes

QR codes can be used to configure Collect on a fleet of devices. The QR code displayed
on the Configure via QR code screen contains all of your current General and Admin
settings. When this QR code is scanned from the ODK Collect app on another device,
the settings from the code are imported and other settings are reset to their defaults.

Note: QR codes generated by Collect only contain settings with non-default values.
When a code is scanned in, settings not explicitly included in the code are reset to
their default values.

92 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

Warning: Settings QR codes contain the admin and server passwords in plain
text. To remove them from the code, tap the warning on the QR code screen.

Scanning a QR code

Navigate to the Scan page to scan an existing QR code and import all of its settings.
The settings contained in the QR code will be set and all others will be reset to their
defaults.

Sharing a QR code

You can tap on the icon to share the QR code as an image. When you click on it, it
displays a list of applications and services like whatsapp, facebook, hangouts, bluetooth,
MMS which can be used to share the QR code. This is useful when there are several
different data collection sites and all devices have to be configured in the same way, in
which case the QR code can be shared from one reference device.

Warning: Since the QR code encodes compressed plain text settings and may
contain the admin and server passwords, you should be careful about how you share
it. For example, if you print out the QR code and tape it on wall, someone could
use a standard QR code scanner to get the admin password.

Importing settings from an image saved on your device

You can import settings from a QR code saved on your device by clicking on the icon
which is located to the right of the share icon. Then select the Import QRCode option.

Making your own QR code

The contents of a settings QR code is a JSON object with two objects for general and
admin settings. The JSON structure is the following:

{
"general": {
"protocol": "google_sheets",
"constraint_behavior": "on_finalize"
},
"admin": {

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 93


Chapter 4. Using ODK Collect

"edit_saved": false
}
}

The JSON object is compressed using zlib before building the QR code. To build your
own code:
1. Write a JSON object containing the changed settings with a structure as shown
above.
2. Compress it using zlib.
3. Build a QR code from the resulting data.
You can either scan the generated QR code or transfer it to your device and then
import it by clicking on Import QRCode option.

List of keys for all settings

Here are the keys for all settings and the set of values they can take:

{
"admin" : {
"admin_pw": String,

// User access control to the main menu. The default value is true.
"edit_saved": Boolean,
"send_finalized": Boolean,
"view_sent": Boolean,
"get_blank": Boolean,
"delete_saved": Boolean,
"qr_code_scanner": Boolean,

"change_server": Boolean,
"change_app_theme": Boolean,
"change_app_language": Boolean,
"change_font_size": Boolean,
"change_navigation": Boolean,
"show_splash_screen": Boolean,
"maps": Boolean,
"periodic_form_updates_check": Boolean,
"automatic_update": Boolean,
"hide_old_form_versions": Boolean,
"change_autosend": Boolean,
"delete_after_send": Boolean,
"default_to_finalized": Boolean,
"change_constraint_behavior": Boolean,

94 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.3. Collect Menus, Settings, and Security

"high_resolution": Boolean,
"image_size": Boolean,
"guidance_hint": Boolean,

"instance_form_sync": Boolean,
"change_form_metadata": Boolean,
"analytics" : Boolean,

"moving_backwards": Boolean
"access_settings": Boolean,
"change_language": Boolean,
"jump_to": Boolean,
"save_mid": Boolean,
"save_as": Boolean,
"mark_as_finalized": Boolean,
},

"general" : {

// Server
"protocol": {"odk_default", "google_sheets", "other_protocol"},
"server_url": String,
"username": String,
"password": String,
"formlist_url": String,
"submission_url": String,
"selected_google_account": String,
"google_sheets_url": String,

// User interface
"appTheme": {"light_theme", "dark_theme"},
"app_language": BCP 47 language codes. The ones supported by Collect␣
,→are: {"af", "am", "ar", "bn", "ca", "cs", "de", "en", "es", "et", "fa",

,→"fi", "fr", "hi", "in", "it", "ja", "ka", "km", "ln", "lo_LA", "lt", "mg",

,→ "ml", "mr", "ms", "my", "ne_NP", "nl", "no", "pl", "ps", "pt", "ro", "ru

,→", "si", "sl", "so", "sq", "sr", "sv_SE", "sw", "sw_KE", "te", "th_TH",

,→"ti", "tl", "tr", "uk", "ur", "ur_PK", "vi", "zh", "zu"},

"font_size": {13, 17, 21, 25, 29},


"navigation": {"swipe" ,"buttons" ,"swipe_buttons"},
"showSplash": Boolean,
"splashPath": String, // Absolute path to splash image

// Maps
"basemap_source": {"google", "mapbox", "osm", "usgs", "stamen", "carto"}
,→ ,
"google_map_style": {1, 2, 3, 4},
"mapbox_map_style": {"mapbox://styles/mapbox/light-v10", "mapbox://
,→styles/mapbox/dark-v10", "mapbox://styles/mapbox/satellite-v9", "mapbox://

,→styles/mapbox/satellite-streets-v11", "mapbox://styles/mapbox/outdoors-v11

,→"},
Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 95
Chapter 4. Using ODK Collect

"usgs_map_style": {"topographic", "hybrid", "satellite"},


"carto_map_style": {"positron", "dark_matter"},
"reference_layer": String, // Absolute path to mbtiles file

// Form management
"periodic_form_updates_check": {"never", "every_fifteen_minutes",
,→"every_one_hour", "every_six_hours", "every_24_hours"},

"automatic_update": Boolean,
"hide_old_form_versions": Boolean,
"autosend": {"off", "wifi_only", "cellular_only", "wifi_and_cellular"},
"delete_send": Boolean,
"default_completed": Boolean,
"constraint_behavior": {"on_swipe", "on_finalize"},
"high_resolution": Boolean,
"image_size": {"original", "small", "very_small", "medium", "large"},
"guidance_hint": {"no", "yes", "yes_collapsed"},
"instance_sync": Boolean,
"analytics": Boolean,
"metadata_username": String,
"metadata_phonenumber": String,
"metadata_email": String,
},

User Access Control Settings

Main Menu Settings Displays a list of Main Menu features. To hide features, uncheck
them.
User Settings Displays a list of user settings and other features accessible in the General
Settings screen. To hide features, uncheck them.
Form Entry Settings Displays a list of features related to viewing and filling out forms.
To disable features, uncheck them.
Moving backwards If you disable moving backwards, the enumerator cannot use the
back button or swipe right to move backwards through a form.
However, disabling this feature does not completely restrict a user’s ability to
access already-answered questions. So, when you uncheck this box to restrict
backward movement, the app will suggest several additional restrictions which
will prevent a non-admin user from revisiting already-asked questions:
• Disable Edit Saved Form option in the main menu
• Disable Save Form option in the Form entry menu

96 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.4. Viewing filled forms on a map

• Disable Go To Prompt option in the Form entry menu


• Set Constraint processing to validate upon forward swipe in the Form Man-
agement settings

Select YES to set these additional restrictions.

Note: When you enable the moving backwards option, you have to configure
the other changed settings since they are not automatically changed back.

4.4 Viewing filled forms on a map

New in version 1.25: ODK Collect v1.25.0


If you are collecting data related to physical locations, you can see a map of all filled forms
from the Fill Blank Form menu. Use the map view to see your progress, to identify filled
forms with bad locations and to plan your travel to the next location to survey.

Note: Blank forms must be downloaded with Collect v1.25 or later. Previously-downloaded
forms will not have corresponding maps. If you update a form downloaded before Collect

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 97


Chapter 4. Using ODK Collect

v1.25 and open its map, only filled forms created with the new form version will be displayed.
Any previously-filled forms will not be included.

In the Fill Blank Form list, form definitions with a geopoint question outside of any repeat
have a map button. Tap on the map button to open a map showing the filled forms for
that form definition. The first geopoint question in the form definition that is outside of
any repeat is used to map filled forms. The first geopoint question can be one that either
requires user intervention or gets the location in the background. On the map, you will also
see your current position and be able to fill a new instance of the current form definition.

4.4.1 Form instance map markers

Filled forms are represented by colored map markers. The color of each map marker indicates
the status of the filled form:
• Blue: saved and unfinalized
• Purple: finalized
• Green: sent
• Red: send attempt failed
Tapping on a map marker will open the filled form for viewing or editing depending on
the form status. By default, forms with Saved, Finalized, and Submission Failure status
are opened for edit and Sent forms are opened for viewing. However, if the Edit Saved
Form button is made unavailable from the admin settings, forms with Saved, Finalized, and
Submission Failure status are opened as view-only.

4.4.2 Map controls

There are three control buttons clustered at the top right of the map. The top button is used
to zoom to the current location. The middle button adjusts the zoom level to ensure that
all mapped filled forms are displayed on the screen. The last button is used to change layers
if offline layers are available. The basemap and reference layer settings are used across all
of Collect so the same ones will be used for this form map as for location widgets with maps.
The button at the bottom right of the screen can be used to fill a new instance of the current
form definition. After you save a new filled form, you will be returned to the map and the
filled form will be displayed if it has a geopoint associated with it.

98 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.


4.5. Using Offline Maps

4.4.3 Status bar

The bar at the bottom of the screen displays the total number of saved forms and how many
of these are shown on the map. All filled forms with a value for the first geopoint question
will be displayed. To ensure that all filled forms are displayed, make the identifying geopoint
question required.

Note: Deleted or encrypted filled forms are not shown on the map. However, forms that
were successfully sent and then deleted and forms that are encrypted both contribute to the
total number of saved forms. See Deleting Forms for more on how filled form deletion works.

4.5 Using Offline Maps

Collect’s geopoint, geotrace, and geoshape questions can be configured to display different
map data. The Maps Settings let you select a basemap to show, as well as a reference layer
to show on top of the basemap.
The data for all the available basemaps comes from services on the Internet, so the basemap
will only be visible to users who are online. To choose a basemap, select a Source and then
a Style if multiple styles are available.
For the reference layer, however, you can select a file on the device, and it will be visible
offline. Offline layers are useful to present custom geospatial data layered over standard
basemaps or as basemaps for low-connectivity environments. Use them to display high-
resolution imagery, annotated maps, heatmaps, and more. ODK Collect can display any
map layer saved as a set of tiles in the MBTiles format.

Warning:
• Vector MBTiles (with data in Mapbox Vector Tile format (pbf)) are only supported
if Mapbox is selected as the basemap source.
• Vector MBTiles are currently displayed without styling. Each layer’s lines are
displayed in a different color picked by ODK Collect. This color will be the same
across all devices using the same MBTiles file. Fills are not displayed.

4.5.1 Offline maps quick start

1. Get or create your MBTiles file with TileMill or other software.


2. Transfer tiles to devices. The MBTiles file must be placed on your device in the layers
subdirectory of your Collect directory, and the filename must end in .mbtiles.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 99


Chapter 4. Using ODK Collect

3. Select your offline layer in the reference layer settings.


4. Open a geopoint, geotrace, or geoshape question.
5. While viewing the map, you can also select the offline layer using the button that looks
like a stack of layers.
MBTiles files typically contain metadata that specifies the range of zoom levels in which
they are visible. If you are viewing at an appropriate zoom level, your offline layer should
be displayed. If you don’t see it, you might need to zoom in or out until the zoom level is in
the range specified by the MBTiles file.
If the tileset has transparency (PNG or PBF tiles only), the selected basemap will show
through. If it does not have transparency or you are offline, only your offline layer will be
displayed.

4.5.2 Getting map tilesets

For non-commercial community mapping activities, Mapbox can arrange for offline MBTiles,
including processed streets, satellite, and custom data. Contact community[at]mapbox.com
for offline Terms of Service exemptions and to receive technical guidance.
To create MBTiles files, use one of the compatible applications . Commonly used free
software packages are TileMill and QGIS with the QTiles plugin. In general, you should
build raster (jpg or png) MBTiles files. Vector (pbf) MBTiles files are only supported with
Mapbox basemaps and are currently displayed without styling.
If you have existing geospatial data that is not in an MBTiles file, you may be able to
convert it for use in Collect. For example, Tippecanoe is a tool to build vector MBTiles files
from GeoJSON features (see warning above: vector MBTiles files are only supported with
Mapbox basemaps and are displayed without styling).

4.5.3 Transferring offline tilesets to devices

MBTiles files must be manually transferred to Android devices to be available to Collect.


Place the MBTiles files in the layers subdirectory of your Collect directory, and ensure
their filenames end in .mbtiles.
To transfer files, you can upload them to an online service such as Google Drive, connect
your device to a computer and transfer them via USB, or use adb.

4.5.4 Selecting offline tilesets

Once an MBTiles file has been transferred to the layers subdirectory of your Collect direc-
tory, it will be available for selection as a reference layer. A reference layer provides useful

100 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
4.5. Using Offline Maps

reference information for a data collector. A reference layer with no transparency acts like
a basemap.
There are two ways to set the reference layer:
• from Maps Settings
• by tapping on the button that looks in a stack of layers in a geopoint, geotrace, or
geoshape question
Both options set the reference layer for all geopoint, geotrace, and geoshape questions. The
choices in the Collect layer selection menu will show the name of the tileset (from the
Metadata table in the MBTiles file), as well as the path to the file.
• Advanced Use and Best Practices
– Using Android Debug Bridge with Collect
– Creating Shortcuts to Collect Forms
– Improving Location Performance
– Projecting ODK Collect onto another screen

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 101
Chapter 4. Using ODK Collect

102 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

FIVE

TIPS AND BEST PRACTICES

5.1 Creating Shortcuts to Collect Forms

You can create an app-like shortcut to a specific form in Collect.

1. Click on Apps button at the bottom of the screen.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 103
Chapter 5. Tips and Best Practices

2. Touch and hold on an empty space on the Home screen and then click on Widgets
button at the bottom of the screen.

104 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.1. Creating Shortcuts to Collect Forms

3. Find the ODK Form widget and then touch and hold it.

4. A menu pops up listing all the available forms. Select the form you wish to create a
shortcut for.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 105
Chapter 5. Tips and Best Practices

5. Shortcut for the selected form will appear on your home screen. You can move the
shortcut to the desired position by drag and drop.

106 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.1. Creating Shortcuts to Collect Forms

Note: To delete the shortcut, hold and press it. A Remove button will appear on the
top right corner. Drag and drop the shortcut to the Remove button. The shortcut will be
removed.

Tip: If you are unable to find Widgets option:


1. Click on Apps and then click on three dots at the top right corner of your screen.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 107
Chapter 5. Tips and Best Practices

2. Click on Help option in the dropdown.

108 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.1. Creating Shortcuts to Collect Forms

3. Click on Adding Items option in the menu which appears.

4. Information about adding widgets will be displayed. You can then follow it or try it
to find the Widgets button.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 109
Chapter 5. Tips and Best Practices

5.2 Improving Location Performance

When you need to specify location in any survey form, you may get a warning message which
says: Sorry, location providers are disabled and a screen will open asking you to enable
location providers.

110 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.2. Improving Location Performance

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 111
Chapter 5. Tips and Best Practices

5.2.1 Enable/Disable location providers

To turn your device’s location providers on/off:


1. Open your device’s Settings app.

2. Tap Location.

112 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.2. Improving Location Performance

Tip: If you don’t see ”Location”, tap Security & Location and then Location.

3. Turn Location on or off.

5.2.2 Change location mode

You can also choose your location mode based on accuracy, speed, and battery use. Android
can help improve location accuracy by triangulating your location off nearby Wi-Fi access
points or cell towers. Combined with data available from your ailing GPS signal, turning on
Wi-Fi will greatly improve location accuracy under most conditions.
In the Location section, tap on Mode.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 113
Chapter 5. Tips and Best Practices

Fig. 5.1: Location providers disabled.

114 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.2. Improving Location Performance

Fig. 5.2: Location providers enabled.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 115
Chapter 5. Tips and Best Practices

Then pick:
• High accuracy: This mode uses GPS, Wi-Fi, mobile networks, and other sensors to
get the highest-accuracy location. It uses Google’s Location service to help estimate
your device’s location faster and more accurately.
• Power saving or Battery saving: This mode uses sources that use less battery, like
Wi-Fi and mobile networks. It uses Google’s Location service to help estimate your
device’s location faster and more accurately.
• GPS only or Device only: This mode uses only GPS. It doesn’t use Google’s Lo-
cation service to provide location information. It can estimate your device’s location
slower and use more battery.

116 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.2. Improving Location Performance

5.2.3 Improve location accuracy

You can also improve accuracy of location.


Tap on Improve accuracy in Location section.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 117
Chapter 5. Tips and Best Practices

Then enable:
• Wi-Fi scanning: Allow apps and services to scan for Wi-Fi networks automatically,
even when Wi-Fi is turned off.
• Bluetooth scanning: Allow apps and services to scan for and connect to nearby
devices automatically via Bluetooth, even when Bluetooth is turned off.

118 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

Note: Google has added Bluetooth scanning support to further improve location accuracy
with Android 6.0 Marshmallow.

For more details on location services, see this guide.

5.3 Android security recommendations

5.3.1 Turn on data encryption

Turning on Android-level data encryption means when the device is locked, no one can
see the data. Unlocking your encrypted device decrypts your data. Encryption can add
protection in case your device is stolen. It’s an easier alternative to using encrypted forms
that offer most of the benefits.

Tip: Encryption takes an hour or more to complete. Before you start, ensure that battery
is charged and keep the device plugged in until encryption is complete. Make sure your data
is backed up, just in case something goes wrong.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 119
Chapter 5. Tips and Best Practices

Warning:
• Interrupting encryption process may lead to loss of some or all of your data.
• The process is irreversible. The device cannot be decrypted once the encryption
is setup and you will have to wipe out all the data for decryption or removing
encryption.

Note: For devices running any version older than 4, you’ll need to either upgrade your
operating system or consult the manufacturer’s instructions.

For devices running Android version 4 or later:


1. Open your device’s Settings app.

2. Tap Lock screen in the Device section. Then tap on Screen lock and create a pin or
password.

120 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 121
Chapter 5. Tips and Best Practices

Note: Encryption cannot be performed until you have setup either a PIN or a
password lock. Pattern lock is not allowed with encryption.

Tip: Setting a strong passcode is imperative to protect your Android phone. The
longer the passcode (or alphanumeric password), the tougher it will be for an attacker
to gain access to your device. Even a lock screen won’t necessarily prevent a thief or
hacker from getting access to your data. You can use apps that destroy all the data
after few failed attempts to unlock the device. For more details, see this.

3. Tap Security in the System section.

122 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

4. Go to Encryption section. Now select Encrypt device to start encryption. Follow the
onscreen instructions. During encryption, your device might restart several times.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 123
Chapter 5. Tips and Best Practices

Note: On some phones, you’ll need to choose Storage, then Storage encryption or
Storage → Lock screen and security → Other security settings to find the Encrypt
device option

Note: If you are using SD card for storage, you can encrypt that too by choosing Encrypt
SD card in the Encryption section. This not only encrypts the contents of the SD card, but
it also means that the card cannot be used on another device unless it is wiped.

Tip: You should also ensure that device debugging (via adb) is disabled when collecting
data, as that can enable users to pull data from the device after it has been successfully
booted (when the sdcard encryption key is entered). i.e., if the debugging interface is enabled,
someone could steal the device, connect it to a laptop, and pull data off it as long as it has
not been shut down as they don’t need to successfully unlock the device’s lock screen to gain
access.

For more details on encryption, see this.

124 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

5.3.2 Adjust Google Play to require a password for every purchase

You can set up Google Play to require a password for every purchase, which makes sure
that anything you buy is done so with your consent. This can prevent enumerators from
installing apps which can bypass certain specified requirements.
1. Open the Play store app, tap on the left-hand slide-out menu, and then choose Settings.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 125
Chapter 5. Tips and Best Practices

2. Look for Require password for purchases and tap on it. You’ll be asked to input your
password.

126 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

3. Choose the password input frequency as For all purchases through Google Play on this
device.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 127
Chapter 5. Tips and Best Practices

Note: The password will not be set for free downloads. If you want to lock free downloads
as well, use an app locking app like AppLock.

5.3.3 Disable cloud-based backup

Though storing your data in the cloud is good for backing it up, law enforcement can demand
that Google turn over your data. The best way to keep your Android phone from sending
your personal data to its servers is to turn off backup. The downside is if you lose your
phone, you may lose your data. Remember, you always have the option to manually back-up
to your personal computer.
To disable backup:
1. Go to Settings app.

128 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

2. Then tap Backup & Reset in Personalisation section.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 129
Chapter 5. Tips and Best Practices

3. Now switch off the option to Back up my data.

130 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

5.3.4 Limit who can use Google Now

Google Now is your own intelligence assistant by bringing information to you when you need
it but that gives Google a lot of access to your data to know what to dig up. The best way
to use it is by turning it off from the lock screen, so only you with your passcode can use
the feature and get access to your personal data. The steps to do this are as follows:
1. Open the Google app, tap on the left-hand slide-out menu, and then choose Settings.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 131
Chapter 5. Tips and Best Practices

2. Tap on Voice in the Search section and then choose ’OK Google’ detection.

132 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

3. Turn off the feature Say ”OK Google” any time.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 133
Chapter 5. Tips and Best Practices

5.3.5 Lower your phone’s sleep timeout

Lowering your phone’s sleep timeout can prevent opportunistic people from getting access
to your unlocked device. The lower the figure, the quicker it locks you out.
1. Start by going to Settings app.

134 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

2. Tap on Display and wallpaper under the Device section.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 135
Chapter 5. Tips and Best Practices

3. Tap on Screen timeout and lower the screen timeout by choosing an appropriate timeout
from the list.

136 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

4. Once you’ve lowered your phone’s sleep timeout setting, you need to make sure that
your Android device locks and presents the lock screen when it wakes up. Tap on Lock
screen in the Device section and then tap on Lock automatically option and choose an
appropriate timeout again.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 137
Chapter 5. Tips and Best Practices

138 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

5.3.6 Limit your lock screen notifications

Your lock screen can show a lot about your life. Your Android phone or tablet can limit
what’s shown on the lock screen in order to prevent others from seeing your personal content
as it comes in.
1. Go to Settings app then Tap on Sounds & notifications under the Device section.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 139
Chapter 5. Tips and Best Practices

2. Scroll down and tap on Notifications on lock screen under the Notification section.
You can change how notifications are shown when device is locked setting. The most
privacy conscious setting is to Hide sensitive notification content so that you know
which app is alerting you, without showing its contents.

140 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 141
Chapter 5. Tips and Best Practices

5.3.7 Prevent unauthorized apps from installing

Android devices can run third-party content outside of the Google Play app store. This can
open up a device to malware attacks.
The easiest way to ensure that only verified and malware-checked apps can be installed on
your phone or tablet is:
1. Go to the Settings app and then tap on Security in the System section.

142 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

2. Make sure that the Unknown sources option is turned off. If this option is turned on,
installation of apps from trusted as well as unknown sources will be allowed.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 143
Chapter 5. Tips and Best Practices

5.3.8 Make sure you keep Android up-to-date

Many Android phone makers will now offer monthly security patches to ensure that any
known vulnerabilities will be patched. Install these patches every month. It’s one of the
best ways to ensure that you won’t be attacked by hackers and malware.
1. To periodically check for software updates, go to Settings app.

2. Then tap on About device under the System section.

144 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.3. Android security recommendations

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 145
Chapter 5. Tips and Best Practices

5.4 Projecting ODK Collect onto another screen

This guide helps the users to project ODK collect onto a screen. There are various methods
available to do this, some of the methods are discussed below:

5.4.1 Using Vysor

Vysor is an extension for the Google Chrome browser that connects to an app on your
smartphone. This extension enables you to control your phone from your PC or Mac using
the mouse/trackpad and keyboard.
Before proceeding further make sure USB Debugging mode is enabled:

Enable USB Debugging Mode on Android

1. Go to Settings, choose About phone.


2. Scroll down and tap Build number seven times.

3. Go back to Settings and there you will find Developer options in the menu.

146 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

4. Scroll down and enable USB debugging mode.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 147
Chapter 5. Tips and Best Practices

5. Confirm the action when prompted.

Note: Windows users should make sure that they have downloaded Universal ADB Drivers.

Follow the instructions given below to use Vysor:


1. Make sure you have Google chrome installed, if not download it from here.
2. Download Vysor extension.
3. Click on Add To Chrome

4. Confirm your action by clicking on Add app.

148 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

Warning: On Windows, You may get an error WebGL is not supported

To fix this, follow the procedures given below:


First, we need to enable hardware acceleration:
1. Go to chrome://settings, scroll down and click on Advanced.

2. In the System section, ensure the Use hardware acceleration when available is en-

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 149
Chapter 5. Tips and Best Practices

abled. You’ll need to relaunch Chrome for any changes to take effect. Click on
RELAUCH

3. Then, we need to enable WebGL, go to chrome://flags, scroll down and search


for WebGL 2.0. From the drop-down list choose Enabled.

150 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

Now you can return to Vysor extension and install it again.

5. After adding the extension, you would be able to see it in the chrome toolbar, if it is
not visible there go to chrome://apps and you would be able to see there.

6. Launch the extension and connect your phone through USB.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 151
Chapter 5. Tips and Best Practices

7. Click on Find Devices, select your device and click on Select.

8. After clicking Select, Vysor would be automatically downloaded to your phone, and
you will be able to see your phone screen.

9. Click on the Collect app and there you go, you have successfully projected your phone
screen.

152 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

5.4.2 Using Android Studio

Android Studio is the official IDE for Android. It provides tools for building apps for every
type of Android device. Android Emulator can be used to test your app virtually on any
Android device configuration.
Follow the procedures given below to run your app on the emulator:
1. Download Android Studio with SDK according to your platform.
2. Here is a tutorial on how to set up Android Studio according to different platforms.
3. After installing, launch Android Studio and click on Start a new Android Studio project
or if you have an existing project click on Open an existing Android Studio project.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 153
Chapter 5. Tips and Best Practices

4. To create a new project follow further steps but if you have an existing project skip to
the step 9.
5. Choose your project location and fill out the Application name and click on Next.

154 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

6. Select the Phone and Tablet option and choose your Minimum SDK. Click on Next.

7. Select an Activity, Empty Activity is preferable. Click on Next.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 155
Chapter 5. Tips and Best Practices

8. In Customize the Activity window, don’t change the default options and click on Finish.

156 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

9. After few minutes, you will be able to see the Android Studio main window, click on

icon, alternatively, you can click on Tools then select Android, from the drop-
down menu select AVD Manager.

10. If you are an existing user list of all virtual devices would appear on the screen, to
create a new virtual device, click on + Create Virtual Device…

11. In the Select Hardware window, choose a device definition for your virtual device. I
have chosen Nexus 5, click on Next.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 157
Chapter 5. Tips and Best Practices

12. Select a system image, I have chosen Lollipop version.Click on Next.

13. Enter your AVD Name, choose startup orientation and click on Finish.

158 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

14 Now you would be able to see your virtual device in Android Virtual Device Manager.
Click on to run your Android emulator.

Note: Please wait for some time as Android emulator takes very long time to start.

15. After the emulator is started, you would be able to see the screen of your emulator. :

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 159
Chapter 5. Tips and Best Practices

16. Now click on to see the location of Android SDK.

17. Open the terminal and move to the platform-tools of the SDK directory.

$ cd platform-tools

18. Copy the collect.apk into platform-tools folder. You can download the apk file
from here.
19. Type the following command to see the list connected devices:

160 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

$ adb devices

You should be able to see the emulator along with its port number, e.g emulator-5554, Here
5554 is the port number. If the emulator is not present in the list, restart the emulator.
To install apk file, in the emulator type the following command:

$ adb install collect.apk

If the command is successfully executed, you will find your file in the launcher of your
emulator.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 161
Chapter 5. Tips and Best Practices

Using Command Line

You can also run the emulator using command line. Follow the steps given below to start
your emulator using the command line:

Note: If SDK installation has been put in another drive or folder instead of in its default
location of $USER_HOME or $HOME. Make sure you have set the environment variables according
to that. In the command line type the following command to set environment variables.

set ANDROID_SDK_ROOT=path\sdk\

1. Open the terminal and move to the emulator folder of the SDK directory.

$ cd emulator

2. For the list of available virtual devices, type the following command:

$ emulator -list-avds

Tip: If you are not able to locate emulator.exe file in SDK folder. Type the following
command to know the location of the file:

$ which emulator

162 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
5.4. Projecting ODK Collect onto another screen

On Windows:

> where emulator

3. Use emulator to start the emulator. Here avd_name is the name of Android virtual
device that you have created.

$ emulator -avd avd_name

Note:
1. You can use sdkmanager command to update, install, and uninstall packages for the
Android SDK. This method is not recommended as it is not user-friendly and also
takes time.
To create an emulator you need to download system image for a particular API level.

$ sdkmanager --verbose "system-images;android-19;google_apis;x86"

• The --verbose option or -v option shows errors, warnings and all messages.
• system-images;android-19;google_apis specifies the system image
package for the Android virtual device.
• android-19 specifies the API level. You can choose different API level if
you want.
2. To create and manage Android Virtual device from the command line, you can use
avdmanager.
After downloading system image, you can use the following command to create an
emulator.

$ avdmanager -v create avd --name testAVD -k "system-images;android-19;


,→google_apis;x86" -g "google_apis"

• The create avd option creates a new Android virtual device.


• --name option is a required option which is used to specify name of the
AVD. Here, the name of the AVD is testAVD.
• The -g specifies the system image tag to use for the AVD.
• -k specifies package path of the system image for the AVD.

See also:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 163
Chapter 5. Tips and Best Practices

You can also use Genymotion as an alternative as it is very fast as compared to custom
android emulators. It is also easy to use and configure, and it is available free of cost for
personal use.

5.5 Related Topics

• Intro to Forms in ODK


– Example form questions in Collect
• Encrypted Forms
• Integrating with other Android Apps
– Launching ODK Collect from External Apps
– Launching External Apps

164 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

SIX

ODK CENTRAL

ODK Central is the ODK server. It manages user accounts and permissions, stores form
definitions, and allows data collection clients like ODK Collect to connect to it for form
download and submission upload.
Our goal with Central is to create a server that is straightforward to install, easy to use and
extensible with new features and functionality both directly in the software and with the use
of our REST, OpenRosa, and OData programmatic APIs.

6.1 ODK Central Features

We have a lot of exciting ideas for the future of Central, and we look forward to hearing
yours as well. Here are the features we already support today:
• User accounts and management
• Role-based user permissioning
• Projects to organize users, permissions, and forms
• Form and submission upload and management
– With support for form version updates
– With drafts and testing on initial creation, and on version updates
– With form and submission multimedia or data attachments
– With a table preview of submission data
– Encrypted forms (self-supplied or project managed keys)
– OData live data feed for analysis with tools like Excel and Power BI
• Integrated checklist-based help system
• Automatic, encrypted off-site data backups to Google Drive
• Clean and modern REST API for integration and extensibility

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 165
Chapter 6. ODK Central

• High performance on low-cost hardware or cloud providers


• ODK Briefcase-compatible data output
• ODK Briefcase push/pull support
Here are some (but not all) key features we do not yet support:
• Customizable user roles
See What is coming in Central for more on future features.

6.2 Who should use ODK Central?

We recommend that all new data collection projects use ODK Central because it is in active
development by the core ODK team. ODK Central is a relatively new server. It replaces
ODK Aggregate which is no longer actively developed. Central isn’t as widely deployed as
Aggregate, but its developers have put it through stress testing and it is used in production
by many projects including several large ones.
Central solves some of the biggest problems with Aggregate. Some of our favorite features
are:
• projects let you partition your server into different sandboxes to support multiple in-
dependent teams
• direct upload of XLSForm files makes form management easier
• the OData API makes it easy to synchronize your live form data to desktop visualiza-
tion and dashboard tools
• managed encryption makes the process of handling encrypted form data significantly
easier and in many cases more secure
Please give Central a try and provide your feedback.

6.3 Notes On Performance

Central was designed from early on to be stable, predictable, and fast on limited hardware.
Perhaps most importantly, even under extreme traffic Central is guaranteed to either wholly
succeed or wholly fail each submission. If, for instance, one submission attachment fails
to upload or persist, the entire submission upload will fail and Collect will attempt the
submission again. If Central reports that a submission was successfully uploaded, then all
submitted data was successfully saved.
We have done some work to benchmark Central to verify these claims, and produce some
guideline numbers. Every circumstance is different, and a lot will depend on your form

166 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
6.4. Learn more about ODK Central

design, your geographic location, and other factors. But in general, on the second-cheapest
DigitalOcean configuration at time of writing ($10/month, 2GB memory), we found the
following:
• A 250 question form without attachments could support 500 devices simul-
taneously uploading many submissions without issues, at a rate of roughly
41.2 submissions per second.
• A larger 5000 question form, without attachments, could also support
500 devices submitting data at once, but runs more slowly (~12 submis-
sions/second) and fails about one submission in every 1000 (which can then
be re-submitted without issues).
• Including attachments slows the process down, since there is more data to
shuffle around. Realistically, the number of concurrent users supported in
this scenario will decrease simply because Internet bandwidth in and out
of Central will limit the number of submissions it can see at a time. But
we have tried situations featuring 5MB submissions with 50 devices at once
without seeing issues (though for the mentioned reasons the response rate
drops to between 1 and 2 submissions/second). Additionally, data exports
with attachments take longer and are more memory-intensive.
When you are planning for your installation and selecting a destination to deploy
Central to, keep these numbers in mind. If 500 people submitting data all at the
same time is a distant scenario, you can probably get by with a lower-performance
option. If your deployment is larger than these numbers, consider bumping up
to a more powerful machine. If you aren’t sure, ask around in the forums.

6.4 Learn more about ODK Central

• Setting Up ODK Central


• Using ODK Central

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 167
Chapter 6. ODK Central

168 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

SEVEN

SETTING UP ODK CENTRAL

7.1 Installing ODK Central

Unlike ODK Aggregate, Central does not run on Google App Engine. Instead, it is built
on a new technology called Docker, which is a new kind of virtual machine (VM) system
that allows smaller image files, better performance, and better ways to define how different
pieces should fit together to create a server like Central. Don’t worry if you don’t know what
that means! We have put together step-by-step instructions for our recommended solutions
below:

7.1.1 Using the Sandbox

If you only want to try ODK Central to see if it’s suitable for your project, consider skipping
installation altogether and using the Sandbox installation we’ve provided for exactly this
reason. Do note that since there is only one Sandbox, all Sandbox users will be able to see
each others’ email addresses, form definitions, and submission data, so please be careful if
you have sensitive information you wish to keep secret.
Otherwise, join the ODK Forum and send a personal message to @yanokwa to gain access
to the Sandbox.

7.1.2 Installing on DigitalOcean

If you want your own server but you’re not sure what to do, we recommend installing ODK
Central on DigitalOcean, which provides an excellent starting point for Docker installations
like ours. For most projects, the $5/month tier will be more than enough for your needs.
To learn more about installing on DigitalOcean, please see here.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 169
Chapter 7. Setting Up ODK Central

7.1.3 Installing elsewhere

If you got excited when you heard mention of Docker above, and you already have your own
destination and process for managing Docker deployments, you’re all set to go. ODK Central
is entirely defined via Docker Compose, which means the docker-compose command will
be all you need to manage the entire system.
We would still recommend reviewing the instructions we’ve provided for DigitalOcean start-
ing from this section. In particular, you’ll need to update your submodules after you clone
the repository, and configure your .env file for your installation.

Installing on Amazon EC2

Amazon Web Services (AWS) is one of the many other options for installing Central. It’s a
good idea to read through the instructions we’ve provided for DigitalOcean, as many of the
steps remain the same or similar.
To obtain a server you will need to first create an AWS account. When launching your
instance, select the Ubuntu Server 16.04 LTS Amazon Machine Image (AMI) in step 1. The
t2.micro instance type has the 1GB of memory recommended for if you don’t expect many
forms to be submitted at once and you don’t expect many large media attachments. When
adjusting the security settings open up the ports for SSH, HTTP, and HTTPS. Once you
have launched your instance, go to the Elastic IPs menu option under Network & Security,
then allocate a new address and associate it with your server in order to keep the IP address
for your server consistent.
Before installing ODK Central on your server, you need to you need to install software
dependencies. Install Docker. Steps 1 and 2 of this how to install Docker on Ubuntu 16.04
tutorial should walk you through the necessary commands. In step 2 add the ubuntu user
to the docker group. You also need to install Docker Compose. This how to install Docker
Compose on Ubuntu 16.04 tutorial should walk you through the necessary commands. You
should only need to complete step 1. You can change the version number to 1.24.1.
After installing Docker and Docker Compose you can follow our DigitalOcean instructions
from running git clone https://github.com/getodk/central. Continue with the Digi-
talOcean instructions for logging into ODK Central.

7.2 Installing Central on DigitalOcean

If you’d like to set up an ODK server that’s accessible from anywhere via the Internet,
DigitalOcean provides a one-click configuration that’s nicely geared with nearly all the tools
you’ll need to set up your new server. The only thing it doesn’t do is register a domain
name, which you will have to do in order to obtain a security certificate for your server.

170 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.2. Installing Central on DigitalOcean

Tip: If you have not already created a DigitalOcean account, use our referral link.
DigitalOcean will give you $100 of credit to spend during the first 60 days so that you can
try things out. Once you have spent $25 with them, we’ll get $25 to put towards our hosting
costs.

In general, this installation process will involve five phases:


1. Obtaining a server and loading it with the appropriate base system.
2. Obtaining a web address (domain name) and pointing it at your new server.
3. Obtaining the ODK Central software and installing it on your server.
4. Preparing ODK Central for startup and running it for the first time.
5. Creating your first Central Administrator account and logging into it.
There are also some optional other steps you can take, which you can find at the bottom of
this page.

7.2.1 Obtaining a Server

In this phase, you will create a new server on DigitalOcean, choose a pricing tier, configure
it with the correct base operating system, and start it up.
If you haven’t already, create an account on DigitalOcean. Then, from the DigitalOcean
control panel, use the Create button at the top to create a new Droplet. This is their name
for a server you can access and manage.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 171
Chapter 7. Setting Up ODK Central

At the very top, under Choose an image, switch to the Marketplace tab and select the
Docker option. The version does not matter.

As you continue down this page, there are a few options that may be important to you:
• There is a section for standard droplets and another for more expensive optimized
droplets. In general, you should not need optimized droplets.
• The size option affects a few things, but the most important is the amount of memory
available to your server. Memory does not affect storage space, it sets the amount of

172 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.2. Installing Central on DigitalOcean

”thinking room” the server gets while it’s working on things. If you don’t expect many
forms to be submitted at once and you don’t expect many large media attachments,
you can start with 1GB. Higher-load servers and servers which handle many image or
video attachments may need 2GB or more. It is pretty easy to upgrade to a larger size
later.
• The datacenter region selects where physically your server will be located. If you
have security concerns, this is your chance to decide which country hosts your data.
Otherwise, generally selecting the option with closest geographic proximity to your
users is a good idea.
• If you plan on setting up DKIM (see below), you will want to set the name of the
server to the full domain name you intend to host your server.
• If you are technically savvy and understand what an SSH key is, there is a field here
that you will want to fill in. If not, don’t worry about it.

Tip: If you choose a 1GB machine and you have problems with exporting attachments,
you may wish to add a swapfile.

Once you click on Create, you’ll be taken back to the Droplet management page. It may
think for a moment, and then your new server should appear. Next to it will be an IP
address, which should look something like 183.47.101.24. This is where your server is
publicly located on the Internet. Don’t worry, nobody can do anything with it until you let
them.
Congratulations! With those steps, you have now created a new server which you can access
over the Internet, and started it up. Next, we will get a web domain name address (like
getodk.org) to point at it.

7.2.2 Obtaining a Web Address (Domain Name)

Now is the time to set up a domain name. We will do so, and then configure it so that it
sends users to the server you created in the previous step.
You’ll need to do this for two reasons: a memorable name (like google.com) will be easier
to remember and access than a pile of numbers, and you cannot obtain a security certificate
without one. It is not currently possible to host ODK Central within a subdirectory on
another domain (so, my-website.com/my-odk-server is not possible, but my-odk-server.
com is allowed, as is my-odk-server.my-website.com).
If you already know how to do these sorts of things, feel free to ignore the following instruc-
tions and proceed on your own. You can rejoin us at the next section.
For the rest of us, there are some options here:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 173
Chapter 7. Setting Up ODK Central

• You can pay one of the many popular commercial domain registrars for a full domain
name, like MyOdkCollectionServer.com. Search for ”domain registrar” to find one of
these. These often cost as little as $3/year.
• You can use a free DNS service: we recommend FreeDNS, which has run for a long
time and has a good reputation. With it, you can obtain a free name, albeit with a
fixed second half (like MyOdkCollectionServer.dynet.com). If you choose this route,
we recommend using one of the less popular names, as the heavily occupied names
can run into trouble later on (in particular, obtaining a security certificate from Let’s
Encrypt).
Whichever option you choose, once you obtain a domain name you’ll want to look at Digi-
talOcean’s guide on setting up domain names for your Droplet. In general, you’ll point your
domain name in DigitalOcean’s direction at your registrar, then in DigitalOcean itself you’ll
want to create an A record that points to the IP address we found above.
New domain names take a little bit to get working. Meanwhile, we can get working on
installing the server software.

7.2.3 Installing ODK Central

In this phase of installation, we will log into your new server, obtain the ODK Central
software, load some settings into it, and install it.
First, you’ll need to be able to log into the server itself. If you are an advanced user who
filled in an SSH key above, you’re good to go. Otherwise, click your email for a message
from DigitalOcean with your server password.
Once you have that password in hand, you’ll be able to use the Launch Console button
to log into your server: when it asks for login, type root and press Enter. Then type the
password you were emailed and press Enter again.

174 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.2. Installing Central on DigitalOcean

Once you are in your server, you’ll want to change your password so that people snooping
your email do not gain access. You should be automatically asked for a new password the first
time you log in. If you are not, type passwd and press Enter, then follow the instructions
to choose a new password. From now on, you will use that password to log in.

Changing Server Settings

First, we will want to ensure that Docker starts up whenever the server starts. Docker will
in turn ensure that Central has started up. To do this, run systemctl enable docker.
You will need to change one more thing on this server before we proceed: you will need to
modify the system firewall for Enketo features in Central to work correctly.
The quickest way to do this is to run ufw disable while logged into your server’s command
line prompt. You should see the message Firewall stopped and disabled on system
startup. If so, you have configured the firewall correctly.

For advanced administrators


While it sounds dangerous, disabling your system firewall does not put your server at greater
risk. In fact, most Linux operating systems come with the system firewall disabled.
If you don’t want to disable the firewall entirely, you can instead configure Docker, iptables,
and ufw yourself. This can be really difficult to do correctly, so we don’t recommend most
people try. Another option is to use an upstream network firewall.
The goal here is to ensure that it is possible to access the host through its external IP from
within each Docker container. In particular, if you can successfully curl your ODK Central
website over HTTPS on its public domain name, all Enketo features should work correctly.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 175
Chapter 7. Setting Up ODK Central

Obtaining and Setting Up ODK Central

Now you’ll need to download the software. In the server window, type git clone https://
github.com/getodk/central and press Enter. It should think for some time and download
many things. Then type cd central to start working with the software.

You now have the framework of the server software, but some components are missing. Type
git submodule update -i and press Enter to download them.
Next, you need to update some settings. Type nano .env and press Enter. This will launch
a text editing application.
• Change the SSL_TYPE line to read: SSL_TYPE=letsencrypt. This instructs the server
to attempt to obtain a security certificate from the free Let’s Encrypt provider.
• Change the DOMAIN line so that after the = is the domain name you registered above.
As an example: DOMAIN=MyOdkCollectionServer.com. Do not include anything like
http://.
• Change the SYSADMIN_EMAIL line so that after the = is your own email address. The
Let’s Encrypt service will use this address only to notify you if something is wrong
with your security certificate.
• Hold Ctrl and press x to quit the text editor. Press y to indicate that you want to
save the file, and then press Enter to confirm the file name. Do not change the file
name.

176 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.2. Installing Central on DigitalOcean

Now, we will bundle everything together into a server. Type docker-compose build and
press Enter to do this. This will take a long time and generate quite a lot of text output.
Don’t worry if it seems to pause without saying anything for a while. When it finishes, you
should see some ”Successfully built” type text and get your input prompt back. When that
happens, type docker-compose up --no-start and press Enter.
Once that is complete, congratulations! You have installed your copy of ODK Central. Next,
we need to teach the server how to start it up, and do so.

7.2.4 Starting up ODK Central

Now, run docker-compose up -d to start the server software. The first time you start it, it
will take a while to set itself up. Once you give it a few minutes and you have input control
again, you’ll want to see whether everything is running correctly:
• To see if ODK has finished loading, run docker-compose ps. Under the State column,
you will want to see text that reads Up (healthy). If you see Up (health: starting),
give it a few minutes. If you see some other text, something has gone wrong.
• If your domain name has started working, you can visit it in a web browser to check
that you get the ODK Central management website.
You’re almost done! All you have to do is create an Administrator account so that you can
log into Central.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 177
Chapter 7. Setting Up ODK Central

7.2.5 Logging into ODK Central

If visiting your server domain name address in your browser does not load the ODK Central
management website, you may have to wait a few minutes or hours (possibly even a day) for
the domain name itself to get working. These instructions are explained in further depth on
the page detailing the ODK Central Command Line Tools.
Once you do see it working, you’ll want to set up your first Administrator account. To do
this:
• Ensure that you are in the central folder on your server. If you have not closed your
console session from earlier, you should be fine. If you have just logged back into it,
you’ll want to run cd central to navigate to that folder.
• Then, type docker-compose exec service odk-cmd --email
YOUREMAIL@ADDRESSHERE.com user-create, substituting your email address as
appropriate. Press Enter, and you will be asked for a password for this new account.
• The previous step created an account but did not make it an administrator. To do this,
type docker-compose exec service odk-cmd --email YOUREMAIL@ADDRESSHERE.
com user-promote Enter.
• You are done for now, but if you ever lose track of your password, you can
always reset it by typing docker-compose exec service odk-cmd --email
YOUREMAIL@ADDRESSHERE.com user-set-password. As with account creation, you
will be prompted for a new password after you press Enter.
Once you have one account, you do not have to go through this process again for future
accounts: you can log into the website with your new account, and directly create new users
that way.

7.2.6 Setting Up Monitoring

The last thing you will want to do is to set up server monitoring. Alerts and monitoring are
important because they can inform you of problems with your server before they affect your
data collection project.
You can find instructions for setting up alerts in the DigitalOcean Documentation.
We strongly recommend creating an alert for Disk Utilization. A threshold of 90% is usually
reasonable. By far the most common operations issue we see is servers running out of disk
space as large media attachments pile up. If your server runs entirely out of disk space,
it can crash and become unresponsive. It is best to upgrade your storage plan before this
happens.
If you are familiar with server operations, you may wish to set up some other alerts: CPU
usage and Memory Utilization are the most interesting remaining metrics. However, these

178 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.3. Advanced Configuration Options

are not as important or easily understandable as the Disk Utilization alert, so you may skip
this if you’re not sure what to do here.
You’re done! Congratulations. In the future, you may wish to consult the Upgrading Central
guide, but for now you may begin using ODK Central. The Using ODK Central sections
can help you with your next steps if you aren’t sure how to proceed.

7.3 Advanced Configuration Options

The following sections each detail a particular customization you can make to your server
setup. Most installations should not need to perform these tasks, and some of them assume
some advanced working knowledge on administering Linux web servers. If you aren’t sure
what something means, the best option is probably to skip the section completely.

7.3.1 Configuring DKIM

DKIM is a security trust protocol which is used to help verify mail server identities. Without
it, your sent mail is likely to be flagged as spam. If you intend to use a custom mail server
(see the following section), these instructions will not be relevant to you. Otherwise:
1. Ensure that your server’s name in DigitalOcean matches your full domain name, and
that the hostname does as well. If you had to make changes for this step, restart the
server to ensure they take effect.
2. Now, you’ll need to generate a cryptographic keypair and enable the DKIM configura-
tion. Run these commands:

cd ~/central/files/dkim
openssl genrsa -out rsa.private 1024
openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
cp config.disabled config

3. With the contents of the public key (cat rsa.public), you’ll want to create two new
TXT DNS records:
(a) At the location dkim._domainkey.YOUR-DOMAIN-NAME-HERE, create a new TXT
record with the contents k=rsa; p=PUBLIC-KEY-HERE. You only want the messy
text between the dashed boundaries, and you’ll want to be sure to remove any line
breaks in the public key text, so that it’s all only letters, numbers, +, and /.
(b) At your domain name location, create a new TXT record with the contents v=spf1
a mx ip4:SERVER-IP-ADDRESS-HERE -all where you can obtain the server IP
address from the DigitalOcean control panel.
4. Finally, build and run to configure EXIM to use the cryptographic keys you generated:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 179
Chapter 7. Setting Up ODK Central

cd ~/central
docker-compose build mail
docker-compose stop mail
docker-compose up -d mail

If you see an error that says Can't open "rsa.private" for writing, Is a
directory., you will need to rmdir ~/central/files/dkim/rsa.private, then at-
tempt docker-compose build mail again. If you see some other error, you may need
to first remove your old mail container (docker-compose rm mail).

7.3.2 Adding Swap

If you have installed Central on a 1GB droplet, you may encounter problems exporting
submission .zip files when there are many attachments. Usually, the .zip file will end up
being empty, or much smaller than expected and possibly corrupt.
In this case, the first thing you can try is to add a swap file. We do not recommend adding
swap unless you are struggling with attachment exports, and if you can afford it, upgrading
to a 2GB machine will yield much better results than adding swap. But if you just need
your export to work for now, this can be an effective workaround.
Log into your server so you have a console prompt, and run these commands, adapted from
this article:

fallocate -l 1G /swap
dd if=/dev/zero of=/swap bs=1024 count=1048576
chmod 600 /swap
mkswap /swap
swapon /swap

7.3.3 Using a Custom SSL Certificate

By default, ODK Central uses Let’s Encrypt to obtain an SSL security certificate. For most
users, this should work perfectly, but larger managed internal networks may have their own
certificate trust infrastructure. To use your own custom SSL certificate rather than the
automatic Let’s Encrypt system:
1. Generate appropriate fullchain.pem (-out) and privkey.pem (-keyout) files.
2. Copy those files into files/local/customssl/ within the repository root.
3. In .env, set SSL_TYPE to customssl and set DOMAIN to the domain name you registered.
As an example: DOMAIN=MyOdkCollectionServer.com. Do not include anything like
http://.

180 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.3. Advanced Configuration Options

4. Build and run: docker-compose build nginx, docker-compose stop nginx,


docker-compose up -d nginx. If that doesn’t work, you may need to first remove
your old nginx container (docker-compose rm nginx).

7.3.4 Using a Custom Mail Server

ODK Central ships with a basic EXIM server bundled to forward mail out to the internet.
To use your own custom mail server:
1. Ensure you have an SMTP relay server visible to your Central server network host.
2. Edit the file files/service/config.json.template to reflect your network host-
name, the TCP port, and authentication details. The secure flag is for TLS and
should be set to true if the port is 465 and false for other ports. If no authentication
is required, remove the auth section.

"email": {
"serviceAccount": "my-replyto-email",
"transport": "smtp",
"transportOpts": {
"host": "smtp.example.com",
"port": 587,
"secure": false,
"auth": {
"user": "my-smtp-user",
"pass": "my-smtp-password"
}
}
}

3. Build and run: docker-compose build service, docker-compose stop service,


docker-compose up -d service.

7.3.5 Using a Custom Database Server

Warning: Using a custom database server, especially one that is not local to your local
network, may result in poor performance. We strongly recommend using the Postgres
v9.6 server that is bundled with Central.

ODK Central ships with a PostgreSQL database server. To use your own custom database
server:
1. Ensure you have a PostgresSQL database server visible to your Central server network
host.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 181
Chapter 7. Setting Up ODK Central

2. Ensure your database has UTF8 encoding by running the following command on the
database.

SHOW SERVER_ENCODING;

3. Ensure CITEXT and pg_trgm extensions exist by running the following commands on
the database.

CREATE EXTENSION IF NOT EXISTS CITEXT;


CREATE EXTENSION IF NOT EXISTS pg_trgm;

4. Edit the file files/service/config.json.template to reflect your database host,


table, and authentication details.

"database": {
"host": "my-db-host",
"user": "my-db-user",
"password": "my-db-password",
"database": "my-db-table"
},

5. Build and run: docker-compose build service, docker-compose stop service,


docker-compose up -d service.

7.3.6 Disabling or Customizing Sentry

By default, we enable Sentry error logging on the backend server, which provides the ODK
Central development team with an anonymized log of unexpected programming errors that
occur while your server is running. This information is only visible to the development team
and should never contain any of your user or form data, but if you feel uncomfortable with
this anyway, you can take the following steps to disable Sentry:
1. Edit the file files/service/config.json.template and remove the sentry lines,
starting with "sentry": { through the next three lines until you remove the matching
}.
2. Build and run: docker-compose build service, docker-compose stop service,
docker-compose up -d service.
If on the other hand you wish to use your own Sentry instance, take these steps:
1. Create a free account on Sentry, and create a new nodejs project.
2. The new project will generate a DSN of the format https://SENTRY_KEY@sentry.io/
SENTRY_PROJECT.
3. In files/service/config.json.template, replace SENTRY_KEY and
SENTRY_PROJECT with the values from step 2.

182 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.4. ODK Central Command Line Tools

{
"default": {
"database": {...},
"email": {...},
"env": {...},
"external": {
"sentry": {
"key": "SENTRY_KEY",
"project": "SENTRY_PROJECT"
}
}
}
}

The error logs sent to Sentry (if enabled) are also being written to /var/log/odk/stderr.
log in the running backend container.

7.4 ODK Central Command Line Tools

ODK Central allows some administrative actions to be performed by anybody with direct
console access to the server itself. Usually, this means only the person who set up the server
and installed Central onto it. These tools can be used to:
• create new user accounts,
• reset passwords,
• and manage user permissions.
All of these actions can be done through the website, and if everything is working normally
we strongly recommend that you use the web interface to perform these actions. But things
happen, and if something gets broken (like everybody forgets their password, or someone
deletes all the users), you can use the command line tools to get things working again.

7.4.1 Getting to the tools

First, you’ll need to get to the tools. You’ll need to log into your server’s command line
prompt again, like you did when you first set up the server. If you used our DigitalOcean
installation steps but can’t quite remember how to do this, we suggest reviewing the section
Installing ODK Central as a reminder, or if you can’t remember your password to start at
the top of that section to reset your password.
Once you have a command line in front of you (it should say something like
root@server-name:~#), you’ll want to enter the following commands:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 183
Chapter 7. Setting Up ODK Central

cd central
docker-compose exec service odk-cmd

If you see instructions appear with the section headings Usage, Options, and Commands,
you’ll know you’re in the right place. If you are familiar with command line tools in general,
those instructions are probably all you need to get going. Otherwise, please see the sections
below for a short guide and example on how to use each one.

7.4.2 Creating a Web User by command line

If you followed our DigitalOcean installation steps, then you’ve already done this once down
in this section. You shouldn’t have to do this again unless you deleted all your users. But if
you do, please start by performing the steps above in the Getting to the tools section. Then,
this is what you would type, assuming your email address is example@getodk.org:

docker-compose exec service odk-cmd --email example@getodk.org user-create

You will be asked for a password for the account, and if everything worked correctly you
should see some data printed out that among other things lists the email you entered a
moment ago. The next thing you’ll need to do is to make the new account an administrator,
which is normally automatically done by the web interface. If you don’t, the new user will
not be able to do anything.

7.4.3 Setting a Web User password by command line

You can always reset any user’s password from the website login page, which will send them
an email with a link to set their new password. However, if for instance that email address no
longer works, or the email is getting lost somehow, you can directly set any user’s password
with the command line tools.
Please start by performing the steps above in the Getting to the tools section. Once you do,
here is what you would type, assuming the email address of the account you wish to set a
password for is example@getodk.org:

docker-compose exec service odk-cmd --email example@getodk.org user-set-password

You will be prompted for a new password. Type it in and press Enter, and if you see text
that says true, the action succeeded. You can then use the website to log into that user
account.

184 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.5. Upgrading Central

7.4.4 Promoting a Web User to administrator by command line

In the current release of ODK Central, all users created by the website interface are au-
tomatically administrators. If you create a user using the user-create tool shown above,
however, you’ll have to perform that step manually. If you do not, the user will be unable
to do much of anything at all once they log in.
Please start by performing the steps above in the Getting to the tools section. Once you do,
here is what you would type, assuming the email address of the account you wish to make
an administrator is example@getodk.org:

docker-compose exec service odk-cmd --email example@getodk.org user-promote

If the action succeeded, you will see text that reads {"success":"true"}.

7.5 Upgrading Central

We release new versions of Central regularly. You do not have to upgrade to the latest
version immediately, but we generally recommend that you do so to get access to the newest
features, bug fixes, and security updates.

Note
You can check your current version by adding version.txt to the URL. For example https:
//sandbox.central.getodk.org/version.txt.

To perform an upgrade, you’ll first need to get to the software. You’ll need to log into your
server’s command line prompt again, like you did when you first set up the server. If you
used our DigitalOcean installation steps but can’t quite remember how to do this, we suggest
reviewing the section Installing ODK Central as a reminder, or if you can’t remember your
password to start at the top of that section to reset your password.
Once you are logged into your server, navigate back to the project folder (cd central).
Then, get the latest version of the infrastructure: git pull.
(If you have made local changes to the files, you may have to start with git stash, then run
git stash pop after you perform the pull. If you aren’t sure, just run git pull anyway
and it will tell you.)
Now, get the latest client and server: git submodule update -i. Then, build your server
from the latest code you just fetched: docker-compose build.

Note

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 185
Chapter 7. Setting Up ODK Central

If you run into problems with this step, try stopping the Central software (docker-compose
stop) and retry docker-compose build after it has shut down the Central website.

Finally, restart the running server to pick up the changes: docker-compose stop and
docker-compose up -d.

7.5.1 Upgrading to Central 0.9

Particularly if you are installed on DigitalOcean, you will need to modify the system firewall
for Enketo features in Central to work correctly.
The quickest way to do this is to run ufw disable while logged into your server’s command
line prompt. You should see the message Firewall stopped and disabled on system
startup. If so, you have configured the firewall correctly.

For advanced administrators


While it sounds dangerous, disabling your system firewall does not put your server at greater
risk. In fact, most Linux operating systems come with the system firewall disabled.
If you don’t want to disable the firewall entirely, you can instead configure Docker, iptables,
and ufw yourself. This can be really difficult to do correctly, so we don’t recommend most
people try. Another option is to use an upstream network firewall.
The goal here is to ensure that it is possible to access the host through its external IP from
within each Docker container. In particular, if you can successfully curl your ODK Central
website over HTTPS on its public domain name, all Enketo features should work correctly.

7.6 Backing Up Central

ODK Central features an off-site backup system to keep your data safe. For each backup,
we extract all your data (including user accounts, forms, and submissions), we encrypt it so
that only you can access it, and we send the encrypted result to your Google Drive account
for safekeeping.

About Google Drive account access


When ODK Central requests to connect to your Google Drive account, it only requests
permissions from Google to:
• Create new files and folders in your Drive
• Read and modify files and folders that it created

186 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.6. Backing Up Central

This means that ODK Central cannot read or modify any other files or folders in your Drive,
no matter what.

To see your current backups status, navigate to → System at the top of the Central man-
agement website. You should see a status page for backups that looks something like this:

7.6.1 Setting up backups

1. To set up a new automated backup, click on the Set up now button on the right.

Tip: If you see a Terminate button instead of a Set up now button, you already
have an automated backup configured. Right now, you can only have one automated
backup scheduled at a time. If you wish to change where the backup is saved, you will
need to terminate the old one before creating a new one.

2. You’ll be asked to enter an optional passphrase. This passphrase is what the server
will use to encrypt your backups. You will be unable to restore the backup without
the passphrase, exactly as you type it in here. If you leave this field blank, we will
still encrypt your backup data but anybody will be able to decrypt it by doing nothing
more than leaving the passphrase blank.
3. The next step talks about connecting to your Google Drive account to store your
backups. When you press Next again, a Google permissions page will appear in a
popup. You will need to press Allow to proceed. If you are feeling unsure about
granting access, please see the ”About Google Drive account access” note at the top
of this page.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 187
Chapter 7. Setting Up ODK Central

4. Once you press Allow, you will see a screen in the popup which contains a lengthy
code, and instructions to copy and paste it back into ”your application.” Copy the
code, switch back to the ODK Central website, and paste it into the Confirmation text
box. Press Next to confirm it.

188 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
7.6. Backing Up Central

5. The setup box should close and you should see a message telling you Success! Auto-
mated backups are now configured.
6. Backups are scheduled to run once a day, at 02:00 server local time. If more than 24
hours pass without a backup completing successfully, you’ll want to double check that
everything has been correctly set up.

7.6.2 Restoring a backup

Restoring a backup to an ODK Central instance will entirely replace all of its data with
the backup. Please be very sure you are restoring to the right place with the right backup
snapshot before proceeding.
1. The first thing you’ll have to do is download your backup from Google Drive, which
you can do from the Google Drive website. You will find the backups in a folder called
ODK Backups. Each file is a single backup snapshot, and each snapshot should be titled
backup-{date}T{time}Z.zip.
2. Once you have the file on your local computer, you will have to transfer that backup
snapshot file to your ODK Central server. If you don’t know how to do this, and
you used our DigitalOcean installation guide, please see their instructions on how to
transfer a file to a Droplet.
3. Once the file is on the server itself, you’ll need to log back into it, like you did when
you first set up the server.

Tip: If you used our DigitalOcean installation steps but can’t quite remember how
to do this, we suggest reviewing the login steps.

4. Now you’ll want to put it in a special place where it can be used by the re-
store tool: /data/transfer. If, for example, you uploaded the file to /root/

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 189
Chapter 7. Setting Up ODK Central

backup-2018-01-01T00:00:00Z.zip, you’ll want to run this command in order to


move it:

mv /root/backup-2018-01-01T00:00:00Z.zip /data/transfer/

5. Now you need to run the restore script. Please note again that all data on this
server is about to be replaced by the backup snapshot data! Anybody currently using
the server will be kicked off and all changes made since the last backup will be lost.
When you are sure you wish to proceed, run the following commands:

cd
cd central
docker-compose exec service node /usr/odk/lib/bin/restore.js /data/transfer/
,→backup-2018-01-01T00:00:00Z.zip 'SECRET_PASSPHRASE'

You’ll have to replace the filename following /data/transfer with your own snapshot
filename, and the text SECRET_PASSPHRASE with the passphrase you typed when back-
ups were first set up. If you did not set up a passphrase, immediately press Enter after
you have finished putting the :file‘.zip‘ filename in:

docker-compose exec service node /usr/odk/lib/bin/restore.js /data/transfer/


,→backup-2018-01-01T00:00:00Z.zip

6. The server will think for a while, and then print some more instructions. You will have
to refresh any browser windows you have open to ODK Central to proceed. If you run
into error messages at this step, please read them carefully and then seek help on the
ODK Forum if you are not sure what to do.

190 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

EIGHT

USING ODK CENTRAL

8.1 Managing Users in Central

There are two types of user accounts in ODK Central: Web Users and App Users.
• Web Users have accounts on the Central management website. These accounts are
global across all projects on the server. They can log into the web interface and
perform administrative actions like user management, form upload and management,
and submission data viewing and download.
• App Users can use mobile data collection apps like ODK Collect to connect to Central.
App Users are limited to a single project at a time. Once connected through the app,
they will be able to see the list of forms, download the ones they need, and upload
completed submissions to those forms.
You will need both types of users in order to run a successful data collection project: a Web
User must upload a valid form definition, an App User must upload submissions to it from
their mobile device, and the Web User will then be able to see those submissions in the web
interface and download them for analysis.

8.1.1 Web User Roles

Central features Role-based User permissioning. In the current release of Central, we provide
three roles: Administrator, Project Manager, and Project Viewer. In a future release, you
will be able to define your own roles as you see fit.
By default, Central roles are configured to allow the following:

Action Administrator Project Manager Project Viewer


Projects
Create x
Edit Details x x
Continued on next page

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 191
Chapter 8. Using ODK Central

Table 8.1 – continued from previous page


Action Administrator Project Manager Project Viewer
Archive x x
Project Forms
Create x x
List All x x x
Edit Attachments x x
Edit Details x x
Set State x x
Delete x x
Project Form Submissions
Create (API) x x
View & Download x x x
OData Access x x x
Project App Users
Create x x
List All x x
Revoke Access x x
See Code x x
Web Users
Create x
List All x
Edit Details x
View Email Addr. x
Revoke Password x
Delete x
Server Configuration
Setup Backups x
Stop Backups x

Managing Web Users

You can make Users into Administrators from the site-wide Users panel, and you can assign
them as Project Managers or Viewers on the Settings tab within the Project.
To manage web users, navigate to → Users → Web Users at the top of the Central manage-
ment website. You should see a listing of users that looks like this:

192 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.1. Managing Users in Central

Creating a Web User

To create a new Web User, click on the Create web user button on the right side of the Web
Users listing page. You will see a popup that looks like this:

To create a new Web User, input the email address of the person who should receive access.
Press Create once you are satisfied with the email address.
That email account will shortly receive an email with the subject line ”ODK Central account
created”. If you do not see the email, check your spam folder. In the email, there will be a
link which will allow the recipient to set a password for their new account, after which they
will be able to log in.
The link is only valid for 24 hours. If 24 hours pass and it has not been used, you should
use the Reset Password tool to send them a new link.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 193
Chapter 8. Using ODK Central

Newly created Web Users are only able to log in and edit their profile information. In order
to give them access to do useful work on the server, please read the following section.

Assigning a site-wide Web User Role

As mentioned under Web User Roles above, there are three Roles you may assign to Web
Users in the current release of ODK Central: Administrator, Project Manager, and Project
Viewer. Administrators may perform any action on the system, while Project Managers may
perform any action on their assigned Project(s). Project Viewers may only see created forms
and submissions within the Project they are assigned to, and cannot edit anything.
To learn how to assign a Project Manager or Viewer role, please see the Managing Project
Roles section in the Projects guide.
To assign an Administrator role, navigate to the Web Users administration panel. There,
you should see a table like this one:

Under the Sitewide Role column in the table, you will see dropdown inputs with the options
Administrator and None. To make a Web User an Administrator, change the dropdown next
to their name to Administrator. You will see the page think for a moment, and then it will
inform you that the action is done. To take away Administrator rights from a Web User,
change the dropdown to None.
You will not be able to change your own Role in the system. To change your own Role, you
will need to get somebody else to log in and change it for you.

Resetting a Web User password

Any user may request a reset of their own password by using the link at the bottom of the
login screen:

194 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.1. Managing Users in Central

After submitting the reset form, the user should receive an email with the subject line ”ODK
Central account password reset”. If they cannot find it, they should check their spam folder.
When resetting a password this way, the user’s current password continues to function until
they actually use the link in the email to set a new one.
We also provide a separate way for administrators to directly reset any Web User’s password
in the administration panel for two reasons:
1. In case the user’s password has been stolen and needs to be disabled immediately.
2. In case the user does not know how to do this themselves.
With the administrative reset, the user’s password stops working immediately and they
will be completely unable to log in until a new one is set. They will receive an email
with instructions and a link on how to do this exactly as shown above. To perform the
administrative reset, navigate to the Web Users listing page, and use the Actions menu at
the right side of the table:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 195
Chapter 8. Using ODK Central

Retiring a Web User

When you retire a Web User, their login access will be revoked and they will be immediately
signed out everywhere. They will disappear from the Web Users management list, but any
records that trace their actions (submission uploader or form creator name, or audit log
action initiator, for example) will still show their information.
If a retired Web User attempts to reset their password, they will receive a special email
explaining that their account has been retired.
To retire a Web User, find them on the Web User administration panel, and open the Actions
menu:

From here, select Retire User and follow the on-screen instructions.

8.1.2 Managing App Users

App Users never gain any access to the management website: they do not have email ad-
dresses or passwords associated with their account, only a nickname so you can tell which
is which. Once a Web User creates an App User within some project, a configuration QR
Code will be generated which will grant a mobile device access to that project as that App
User. Access can be revoked at any time, and Web Users can see which App Users uploaded
which submissions.
A newly created App User does not have access to any Forms. To give them access once
they are created, use the Form Access tab on the Project. You will be able to allow access
to particular Forms within the Project for each App User.

Tip: In version 0.6 and earlier of ODK Central, all App Users were granted download and
submission rights on all Forms within their Project. These users retain their access when
you first upgrade to version 0.7. Once you have version 0.7 installed, you can adjust these
Users’ access per form.

To manage App Users, navigate to the project whose App Users you wish to manage, and
then click on the App Users tab just below the project name. You should see a listing of

196 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.1. Managing Users in Central

users that looks like this:

Creating an App User

To create a new App User, click on the Create app user button on the right side of the App
Users listing page. You will see a popup that looks like this:

Once you provide a nickname for the user (usually the name of the data enumerator who
will carry the mobile device works well), click Create. The user will be created, and you will
see a screen that looks like this:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 197
Chapter 8. Using ODK Central

That App User has now been created and granted access to use their mobile device to list,
download, and submit to all available forms within their project. To do so, however, their
mobile device will have to get set up with this new account. That is what the QR Code you
see on this screen is for. Read on to the next section to find out how to use it.

Configuring an App User mobile device

A mobile device will need to be configured to access your ODK Central server as a particular
App User in order to gain access to the forms and upload submissions within their project.
This is done by way of the Collect Settings QR Code.
The QR Code contains information about how to find your ODK Central server, and how
to prove to the server that the mobile device belongs to a valid App User. In future versions
of ODK Central, it will be possible to specify other settings to be imported to the device as
well.
There are two ways to access the QR Code for an App User. The first is in the second step
of the App User creation wizard. Please find the second screenshot in the previous section
to see what this looks like. If you close out of this wizard, you can still access the QR Code
by clicking on the See code link in the listings table:

198 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.1. Managing Users in Central

If instead of a See code link you see text that says Access revoked, that App User no longer
has access to the server. Create a new App User if you need a new QR Code.
Once you have found the QR Code, you will be able to use it to configure ODK Collect.
Please see the section on importing settings into Collect to learn how to do this.

Revoking an App User

You may wish to revoke an App User’s access, for instance if their QR Code has been stolen
or if they have left the organization. To do so, navigate to the App Users listing page, and
use the Actions menu at the right side of the table:

App Users whose access has been revoked will still appear in the App Users listing table,
and will still be visible as the submitter of any submissions they uploaded. However, they
no longer have a valid QR Code with which they can configure an ODK Collect installation,
and any mobile devices already configured with their code will no longer have access to the
project.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 199
Chapter 8. Using ODK Central

8.2 Managing Projects in Central

New as of version 0.4, almost everything in ODK Central is organized by Project. Forms,
Managers, and App Users are all partitioned by project. Both on the administration website
as well as on a mobile device (within ODK Collect, for example), access to each project
and its forms can be managed person-by-person. Only the Central administrative staff can
create and grant initial access to projects.

8.2.1 Projects Overview and Roadmap

Projects are a work in progress that we will add to and improve over the next few releases.
If you are working on ODK Central version 0.4, projects work like this:
• All forms must belong to a project. It is not possible to create a form that is not part
of a project. It is not possible to assign one form to multiple projects (though the same
form may be uploaded to as many projects as desired).
• All App Users (who may access Project Forms through mobile device applications
like Collect) must also belong to a particular project.
– When a user connects to a project through Collect, they will only be able to see
and submit new data to forms within that project.
If you have upgraded to version 0.5, the following changes have been made:
• Only Web Users (who are allowed to administer ODK Central through the man-
agement website) marked Administrator have administrative access to the main site
settings and all projects.
– However, all Web Users created before version 0.5 were already marked Admin-
istrator. You will have to go change their Site-wide Role to None if you wish to
remove these privileges.
• Normal Web Users who are not Administrators can be made Managers on select
projects. These users have the ability to manage anything about the project. They
can:
– Appoint other project managers.
– Create, manage, and archive forms on the project.
– Access all submitted data within the project.
– Create, manage, and retire App Users for the project.
– Manage and archive the project itself.
Since the major changes that occurred in version 0.5, we have additionally made the following
improvements:

200 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.2. Managing Projects in Central

• Better, centralized form state and access management.


• More granular project access, in the form of a Project Viewer role which allows read-
only access only to Forms and Submission data.
In future releases, we have a loose roadmap with at least the following goals:
• Change the relationship between Collect and Central so that with one button you can
synchronize the mobile device to some centrally managed desired state.
– So for instance, you can decide which forms should be available on Collect within
Central once, and within Collect just press ”synchronize” to update to that state.
– Eventually, Collect app settings may be synchronized this way as well.
– And eventually, different App Users of different roles may be assigned different
device states.
• Download an entire project’s data at once.
If you have ideas on how projects might be made more useful for you, please do not hesitate
to leave us feedback on the ODK Forum.

8.2.2 Migrating to Projects

If you have an ODK Central server installed which is version 0.3 or earlier, your existing
data will be migrated into a project when you update.
All of your existing forms and App Users will be placed into a project entitled ”Forms you
created before projects existed”. There are no longer site-wide App Users, so that panel will
no longer be present.

Important: Upgrading to version 0.5


Mobile clients like Collect which were configured to access version 0.3 will continue to work
without intervention for version 0.4, but they must be reconfigured with a new QR Code
access token from Central before migration to 0.5, because for version 0.5 this backwards
compatibility will be removed.
If you do not refresh the access tokens before upgrading to 0.5, you will have to reconfigure
the device with a new QR Code from 0.5 in order to restore the connection.

8.2.3 Creating a Project

Only ODK Central administrators may create projects. To create a project, navigate to the
Projects section of the Central management homepage, and click on the New button.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 201
Chapter 8. Using ODK Central

You will be asked for a name for your new project. When you provide one and press Create,
your project will be created and you will be taken to its management page.

8.2.4 Managing a Project

You can find all the projects you have access to in the Projects section of the ODK Central
management website homepage.

When you click on its name, you will be taken to its management page.

202 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.2. Managing Projects in Central

Here, you will find some basic details about the project, and a listing of all the forms in the
project. You can click on any form name to manage that form and view its submission data.

Editing Project Settings

To edit Project Settings, first navigate to the Project, then click on the Settings tab under-
neath the Project name.

From here, you will be able to edit the Project Name. You will also see a section for Archiving
a Project, which is described in more detail below.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 203
Chapter 8. Using ODK Central

Managing Project Roles

Any Web User may be assigned as a Project Manager or Project Viewer on a Project.
Project Managers may perform any action upon and within that Project, including changing
its name, adding more Project Managers, and uploading and managing Forms and Submis-
sions. Any Web Users that are site-wide Administrators will already be able to perform
these actions on any Project without being explicitly named a Manager.
Project Viewers can view basic information about all Forms in the Project, and download
Submission data or access it over OData for analysis. They cannot make any modifications
to any data or settings.
You will find a detailed breakdown of user roles here.
To assign or remove Managers or Viewers for a Project, first go to the Project overview
page, then click on the Project Managers tab under the Project name. You should see the
following page:

If roles have not already been assigned to the Project, the table will be empty. This is
normal: the table only shows Users with assigned roles on the Project at first. To find a
Web User to assign them a role, search for them in the Search for a user field above the
table. You can find users by their Display Name or their Email. Type part or all of either
into the box, and press Enter. The search results will appear in the table.

204 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.2. Managing Projects in Central

To make a Web User into a Project Manager or Viewer, change the dropdown next to their
name in the Project Role column from None to Manager. You should see the page think for
a moment, and then a confirmation of success. If you clear the search in the text box, the
newly assigned user should remain.
To demote a Web User from any role, change the dropdown back to None.

Managing Project App Users

To manage App Users for a Project, you can navigate to the Project overview page, then
click on the App Users tab under the Project name. For more information about creating,
managing, and retiring Project App Users, please see this section.

Managing Form Access

Right now, Central offers two ways to control around Form Access within each Project:
• Each Form’s Lifecycle State controls whether any App User can download and/or
submit to that Form. Near the end of a Form’s life, for example, it makes sense to
disallow downloading the Form as a blank, but still receive any submissions that have
already been created.
• Access to download and submit each Form can be customized per App User associated
with the Project. When first creating a Form, for example, it makes sense to only allow
a testing user access to the Form so that one can be sure that it works before rolling
it out to all users.
We place these access controls for all Forms in a single place, on the Form Access tab at the
Project level. To access it, navigate to the Project and select the tab at the top of the page
labeled Form Access.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 205
Chapter 8. Using ODK Central

On the left side of the Form Access page, you will find a list of all the Forms in the Project,
along with a dropdown selection to set the Form Lifecycle state for each one. Along the top,
you will see all active App Users in the Project. At each row/column intersection, there is
a checkbox that governs whether each App User is allowed access to each Form.

Tip: You may see a pencil icon next to the Lifecycle state dropdown on some Forms. This
means that those Forms are currently Drafts, with no published version. They will not be
visible to data collection clients no matter the Lifecycle state setting, or the checkboxes on
this page. Once a Draft Form is published, then the settings on this page will immediately
take effect.

If you are having trouble recalling what each Form State means, the ? icon in the header
will give you a quick recap:

206 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.2. Managing Projects in Central

As you make changes to Form States and App User access, they will be highlighted in yellow.
You can make all the changes you’d like to apply at once (for example, marking an old version
of a Form as Closing while granting Open access to the new one), and once you are satisfied
with what you see you can click the Save button at the top-right of the screen to apply them
all at once.

Tip: When you first create an App User, it will not have access to any Forms. When you
first create a Form, no App Users will be allowed to access it.

Archiving a Project

When you Archive a Project, it will appear at the bottom of the Project List on the home-
page, with (archived) added onto the end of its name.
In version 0.6 of Central, archiving a Project would disable certain features on it. We have
eliminated this behavior, so all your archived Projects can still be used and manipulated
freely.
To Archive a Project, first navigate to the Project, then click on the Settings tab underneath
the Project name.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 207
Chapter 8. Using ODK Central

Click on the red Archive this Project button on the right, and follow the on-screen instructions
to proceed.

8.3 Managing Forms in Central

Forms are at the heart of ODK. Once fetched onto a mobile device from ODK Central, they
define the questions, validation, and logic to be presented during data collection. They also
serve to organize the data coming back from mobile devices.

8.3.1 Forms in ODK Central

In ODK Central, there are four important tasks you’ll perform while managing a data
collection project:
1. Form drafting is where you design the Form itself, laying out many details like the
questions and acceptable responses. ODK Central itself does not help with form design:
instead, please take a look at the many available tools and the introduction to form
design for help creating your form. Central does, however, help with testing your
design, with Form Drafts. When you first upload your Form, it will be a Draft to
which you can connect a mobile device and submit test data. If you are not satisfied
with the Form, you can adjust the design and upload a new version in place of the old
Draft. Once you are satisfied, you can Publish the Form to make it ready for use.
2. Form lifecycle settings allow you to control who can access and submit to particular
Forms. These tools can help manage user permissions, but they can also help phase
out outdated Forms as they come to the end of their life. You can control these using
the Form Access tab on the Project.
3. Data extraction and analysis can occur either at the end of the project, or contin-
ually as the project runs. Either way, ODK Central provides several different methods

208 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

for extracting and analyzing your submission data. This is covered in the Form Sub-
missions article.
4. Form updates allow you to make changes to a Form while it is already in use. Central
allows you to create a new Draft of any Form at any time. As with initial Form creation,
this Draft allows you to test your changes in a staging environment where it will not
affect the live Form or its data. When you are satisfied with the Draft, you can again
Publish it, and it will replace the live version.
Drafting and version updates are new as of Central 0.8. We will cover all of these topics in
the sections below.

8.3.2 Uploading a form to ODK Central

As mentioned, ODK Central does not feature a built-in form design utility. Please take a
look at the many available tools and the introduction to form design for help creating your
form.
As of version 0.7, Central will accept either XForms .xml or XLSForm .xls/.xlsx files. If
you have written your own .xml file, we strongly recommend that you first double check that
it is valid using ODK Validate. If you upload an XLSForm spreadsheet, Central will convert
it to an XForm for you, and it will be automatically validated as part of that process.
Once you have your form file, the next step will be to upload it into ODK Central. To do
this, navigate to the Project (click on its name from the ODK Central homepage) to which
you would like to add the Form, and locate the Forms listing section at the bottom of that
page:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 209
Chapter 8. Using ODK Central

From there, click on the New button next to the section header, and you should see a popup
appear:

You can either click on the choose one button to browse for your .xml, .xls, or .xlsx file,
or if you already have it handy somewhere, you can drag it over the gray box and drop it to
choose it. Either way, once you have chosen your file (you will see the name of your file at
the bottom of the gray box when you do), you can click on the Create button immediately
below to upload the form.

210 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

Some errors you may see:


• If you are uploading an XLSForm, and the converter flags warnings with it, your form
will not be immediately created. You’ll be shown the warnings, and given the option
to either ignore them and create the form anyway, or else you can fix the issues and
start over by uploading a new file.
• You may see a message that reads A resource already exists with xmlFormId
value(s) of xyz. If you do, there already exists a form within this project with the
same unique designation. If you are using XLSForm, try changing the name of the file
or the form_id in the settings sheet. If you designed the form by hand, please check
the id="…" attribute immediately inside the <instance> tag.
• You may see a message that says A form previously existed which had the same
formId and version as the one you are attempting to create now. To prevent
confusion, please change one or both and try creating the form again. This
means there once was a form within this project that has since been deleted that has
exactly the same formId (see the previous bullet point) and version designation as the
one you are now trying to upload. Central won’t accept the new form, because this
conflict could cause confusion with mobile devices that still have the old form sitting
around. To upload this form, change either the formId (again, see the previous bullet
point) or update the version and try again.

Once the form is successfully uploaded, you will be taken to the Form Draft page. It will
not be accessible to data collection clients until you publish the Draft, which we will cover
in the following section.

8.3.3 Working with Form Drafts

Form Drafts, available as of Central 0.8, provide a way to safely and easily verify the design
of your Form before you make it available for use. Drafts are accessible only to privileged
Project staff. Each Form Draft has a unique access token which allows configured data
collection clients to submit test submissions to the Draft. These test submissions disappear
automatically when the Draft is published. Once a Draft is published, it is available for use
according to the access rules you have specified in the Form Access tab on the Project.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 211
Chapter 8. Using ODK Central

The Draft Status page gives insight into the current status of your Draft, and provides
controls for managing it.
On the left, you will find the Draft Checklist, which suggests the steps you might take before
publishing your Draft. On the right are details about the currently uploaded Draft version
of the Form, including its current version string, and actions you may take on the Draft:
• The Upload new definition button will allow you to upload a new Form definition,
which will replace the current Draft version. When this happens, all test submissions
will be erased. If you have uploaded Media Files, Central will attempt to preserve any
that match the new definition.
• The Publish Draft button will publish the Draft, making it available for use according
to the access rules you have specified on the Form Access tab on the Project. Any test
submissions you have made will be erased.
• The Abandon Draft button will delete the Draft. When there is not yet a published
version, this will delete the entire Form. If the Form has been published, only the
Draft will be deleted.

Tip: When a form is first created, none of the existing App Users on the project will be
able to access it for download or submission, even once the Form is published. Once you are
ready to allow App Users to access the form, use the Project Form Access tab.

212 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

When you first create a new Form, the navigation tabs on the left will not be accessible. They
pertain to the published version of the Form, and will become available once you publish
your Draft. The tabs on the right, within the gray Draft section, relate to the Draft.
If your Draft requires Media Files, there will be a checklist step asking you to upload them,
and a Media Files tab at the top of the page. See the next section Forms With Attachments
for more information about uploading and managing attachments.
The Testing Draft tab shows test submissions that have been made to the Draft, and in-
structions for doing so:

At the top of the page are instructions and a QR Code which will configure a mobile device
to submit to the Draft Form. For help configuring a mobile device, please see importing
settings into Collect. The table below these instructions contains any test submissions that
have been made to the current Draft. For help with this table or exporting test data, please
see Form Submissions in Central.

8.3.4 Forms With Attachments

If your Form Draft references any external files (images, audio, or video included as part
of your question prompts, or data lookup files used to populate selection lists), Central will
see this and open up some additional displays and controls you will need to provide those
external files:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 213
Chapter 8. Using ODK Central

If you see this extra Upload Form Media Files checklist step and Media Files tab at
the top of your Form Draft checklist, then Central believes you need to upload some files
associated with this form. If the checklist step has been checked off, then you’ve already
completed this task: great work! Otherwise, click on the → Media Files tab at the top to
see what files you’ll need to provide.

This form design references three files that we’ll need to provide, one of which we’ve already
uploaded. You can see the name and expected type of the file in the table, as well as when
the file was last uploaded. You can click on the name of any uploaded file to download what
Central has for it. To upload a new one, you’ll want to drag-and-drop one or more files onto

214 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

the table.

On File Types and Contents


While Central will detect the type of file the form design expects, and will verify that the
name of any uploaded file matches one that is expected, Central will not double-check the
type of the file, nor the contents of the file for you. So, just because Central accepts your file
does not necessarily mean that it will work correctly.

Once you publish a Draft, you will not be able to modify the Attachments associated with
it without creating a new Draft.

Bulk-uploading Many Attachments At Once

If you select and drag many files at once onto the table, Central will automatically try to
match each file with a name in the table. You’ll have a chance to see what it came up with
and confirm that things look okay before the upload begins. You will see a warning if one
or more of your dragged files don’t match any of the expected names.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 215
Chapter 8. Using ODK Central

Uploading One Attachment

If you drag a single file onto the table, you’ll have the option of which table row you’d like
to upload that file into. This way, if the file isn’t named exactly what Central expects, you
can still upload a file into that slot without having to rename it on your own computer. But
if the file does have the appropriate name, you can drop it somewhere other than a specific
slot (for example, just below or just above the table) to have Central match it up with the
correct slot automatically.

8.3.5 The Form Overview page

Here, you can get a brief summary of the status of your form, and recommended next steps.
You are automatically taken here when you publish a Form Draft or click on the form name
in the Form listing page. You can also get back here from other form-related pages by
clicking the → Overview tab below the name of the form.

216 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

The documentation on this page is a more detailed introductory explanation of form man-
agement in ODK Central, but the checklist you find on the Overview page is tailored to the
current status of your form and your project and is a great place to look when you aren’t
sure what to do next.
In the future, look forward to seeing even more useful information at-a-glance on this page.

8.3.6 Seeing Form Submissions

To see the current submissions uploaded to Central for a form, you can click on the →
Submissions tab below the name of the form. Here, you will see a summary table of all
known submissions, and you will find multiple options for downloading and analyzing your
submission data. This page and these options are covered in more detail in the Managing
Form Submissions in Central article.

8.3.7 Managing Form Lifecycle

Forms can be in one of three lifecycle stages: Open, Closing, and Closed. All forms start
in Open state when they are first created. You can see what each of these means below:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 217
Chapter 8. Using ODK Central

State Available for download to apps Accepts new submissions from apps
Open yes yes
Closing no yes
Closed no no

As you can see, you can use the Closing state to prevent further distribution of a form while
still allowing the final few submissions to come in, while the Closed state effectively turns
the form off completely. You can always set the form lifecycle stage to whatever you want:
you can always, for example, re-open a closed form.
To set the form lifecycle stage, go to the Form Access tab for the Project, under the name
of the Project at the top of the page. You may have to navigate back out of the Form first
by clicking on the Back to Project Overview link at the top of the page. Here, you will find
the three possible stages in a dropdown for each Form on the left side of the page. Select
the ones you want for each Form, then click Save at the top-right to save the changes.
You can find more information about the Form Access page here.

8.3.8 Updating Forms to a New Version

As of Central 0.8, it is possible to update a published Form with a new definition, or new
Media Files, and to test these changes before they are applied to the Form in use.
There is one primary restriction Central enforces on updated definitions: once defined in
a published Form version, each field Data Name (in technical terms, the Instance XPath)
cannot change its Data Type. Unused fields may be removed, and new fields may be added,
but if any field reuses a previously existing Data Name, it must have the same Type as it
did before. If you run into an error with this restriction, the easiest solution is usually to
rename the changed field to a new name.
To begin the process of updating a published Form, click on the Create a new Draft button
in the Draft navigation on the Form:

Initially, the new Draft will have the same definition as the published Form. If you only

218 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.3. Managing Forms in Central

want to update attachment Media Files, this means you don’t have to bother uploading a
definition at all: you can go straight to the Media Files tab and upload the changed files.
You can replace the Draft definition, Media Files, and make test submissions as with the
initial Form Draft before the Form was first published. Test submissions will not interfere
with published Form submissions.
Once you are satisfied that your updated Form is ready to be published for immediate use,
you can click on the Publish Draft button on the Draft Status tab.

Form Version naming


If you did not change the definition, or your updated definition did not change the version
of the Form, Central will not be able to publish the Form as-is. This is because the version
must change in order for data collection clients to understand that they should update. You
can upload a new definition with a changed version, or else Central will offer to change it
in-place for you.

Once the Draft has been published, it becomes the version in use and there will no longer
be a Draft associated with the Form.

What happens to my submissions?


When a new Form version is published in place of an old one, all the previous submissions
continue to exist, and will export along with all your data over Zip download or OData.
However, only the current Form definition will be used in that export: if, for example, you
have deleted a field that used to exist, that field will not appear in the export.
Draft testing submissions will never export with your final data, and only exist as long as
the Draft does. If you delete, publish, or replace your current Draft, all test submissions will
be cleared away.

8.3.9 Accessing Older Form Versions

If you have published multiple version of a Form, you can see each of them under the Versions
tab.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 219
Chapter 8. Using ODK Central

Each published version of the Form will be listed, along with actions to download the def-
inition of each Form. In future versions of Central, the Media File attachments associated
with each version of the Form will be downloadable as well.

8.3.10 Deleting a Form

Do not delete a form until you are completely sure you never need a form or its submissions
again. If you only want to turn the form off so that it doesn’t appear to users of mobile data
collection apps, we suggest using the form lifecycle controls explained above.
If you are certain you wish to delete a form, you can find the option on the Form Settings
page: click on the → Settings tab under the name of the form at the top of the page. On
the right side of this page, you will find the Delete this form button.

8.4 Managing Form Submissions in Central

Once you have uploaded a form to ODK Central, connected to it from your mobile device,
and uploaded submissions back to Central, you will see them appear in the Form submissions
page in Central.
To find the Form submissions page, first find the form in the Form listings page (→ Forms)
and click on it. You will be taken to the Form Overview page for that form. Click on the
→ Submissions tab below the form name to find the submissions.

220 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.4. Managing Form Submissions in Central

The table preview you see here will show you the first ten fields of your survey and their
results, with the latest submissions shown closest to the top. Any downloadable files will
appear with a green download link you can use to directly download that media attachment.
The submission’s instance ID will always be shown at the right side of this preview table.
It is not yet possible to screen or delete submissions for quality or edit submission data.
These features are planned for future releases. For now, you will need to pull your data out
of Central before you can work with it. Right now, you can do this in one of two ways:
1. The CSV Download option will get you a .zip file containing one or more .csv
tables, along with any multimedia submitted to the form. This is a good option if you
already have custom tools you wish to use, or you want to import it into an offline
analysis tool like SPSS or Stata.
2. The OData connector allows you connect a live representation of the data to OData-
capable tools like Microsoft Excel, Microsoft Power BI, Tableau, SAP, and others. This
option has some advantages: the data is transferred more richly to maintain more
data format information, and the feed is always live, meaning any analysis or reports
you perform in your tool over an OData connection can be easily refreshed as more
submissions come in.
Learn more about these options below:

8.4.1 Downloading submissions as CSVs

To download all submission data as a .zip of .csv tables, click on the Download all #
records button on the right side of the listing page:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 221
Chapter 8. Using ODK Central

Once it completes downloading, you will find one or more files when you extract it:
• A root table .csv named after your Form title.
• Join table .csv files representing any repeats you may have in your form, with join
columns on the left of each table relating each row to its counterpart in the parent
table. Each join table is named to reflect its relationship with the others. If there is
only one .csv file, then your form has no repeats.
• A folder named files which contains subfolders, each named after an instanceId
of a submission. Each subfolder then contains a set of file attachments relating to
that submission. If no files folder exists, then no multimedia attachments have been
submitted to this form.
• If you have enabled Client Audit Logging on your form, and log events have been
submitted to the server, then you will find a file that ends with - audit.csv. This
file combines all the logging data from all submissions to the form into a single table.

8.4.2 Connecting to submission data over OData

To connect a third-party tool to Central over OData, you will need a link to paste into the
tool. You can find this link by clicking on the Analyze via OData button on the right side
of the listing page:

Once you click on it, you should see this popup appear:

222 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.5. Encrypted Forms in Central

Because OData is a industry standard, only one link is necessary to make most tools work.
However, because it is a relatively new technology, some tools need a little bit of customiza-
tion to work correctly. If you are using such a tool, like Power BI, click on its tab to get the
special link we provide for it. Otherwise, copy the link as-is and paste it into your tool.
For information on how to create an OData connection in Microsoft Excel, click here. For
instructions in Microsoft Power BI, see this page.
If you want to use the free and popular R statistics and analysis tool, we recommend you
use ruODK. A guide for getting started with it can be found here. Just like ODK itself,
ruODK is developed and supported by community members. If you wish to help improve it,
you can find information on GitHub.
When asked for login information, provide the email address and password you use to log
into ODK Central. Make sure you trust the tool you are using before you do this.

8.5 Encrypted Forms in Central

As of version 0.6, ODK Central supports the encryption of submitted data, similar to ODK
Aggregate.

For Aggregate users already using encryption


If you already use encryption with ODK Aggregate, you can use the same encrypted forms
with ODK Central without any change, and decrypt data using Briefcase with the same

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 223
Chapter 8. Using ODK Central

steps you already use today. However, you may still wish to read the rest of this document
to understand what Central does and the easier to use encryption available to you in Central.

8.5.1 Encryption with Central

First, here is what enabling encryption on a project or form will do:


• Collect will encrypt finalized data on the mobile device.
• Submission data is sent encrypted, even if Central is not configured with HTTPS.
• Data (filled forms and their attachments) at rest on the Central server is encrypted,
and can only be decrypted by using the appropriate secret key information.
However, here are some things that encryption will not do:
• Increase the security of user passwords or Collect QR codes.
• Encrypt the blank form contents or attachments.
• Prevent a hijacker from replacing forms or redirecting submissions to a malicious server.
• Prevent the creation of phony submissions.
• Substitute for HTTPS security on the web administration panel.
And, here are some limitations that will appear when encryption is enabled on a project or
form:
• Encrypted submissions will appear only as metadata records over OData. Metadata
like the submitter and the submission date will be available, but none of the actual
data from the form will appear.
• The same restriction applies to the submission preview table on the Central adminis-
tration panel.
• As of version 0.6, enabling encryption will not encrypt already-submitted submissions.
• As of version 0.6, it is not possible to disable project managed encryption (explained
below) once enabled.
• As of version 0.6, submissions using self-supplied key encryption (Aggregate-style en-
cryption) can be retrieved and decrypted only through Briefcase or direct API access.

8.5.2 Central Encryption Modes

We offer two methods of form encryption in ODK Central:

224 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.5. Encrypted Forms in Central

• Self-supplied key encryption is our term for the encryption process already sup-
ported by Aggregate and other ODK ecosystem servers. To use self-supplied key en-
cryption, you must generate and securely store your own cryptographic keys which are
used to perform the encryption and decryption of the data. The public key (which
cannot decrypt the data) is embedded into the XForm itself and this is how it is dis-
tributed with the form to Collect and other mobile clients. Decryption is possible only
with the private key, and only through Briefcase.
• Project managed encryption is new to ODK Central. It uses the same existing
ODK encryption standard under the covers, and so it is compatible with existing
mobile clients like Collect. However, Central will generate and securely store the
cryptographic keys for you. The keys are themselves protected by a passphrase that
you provide, similar to the Central backups encryption system. You do not need to
use Briefcase: if you can supply the correct passphrase, the Central administration
panel will decrypt the data on the fly and provide you with exported data as usual.
Without the passphrase, the data cannot be decrypted, and as Central does not store
the passphrase it cannot decrypt the data without your input.
For most cases, we recommend using project managed encryption. It is easier to
use, as you do not have to learn how to generate a cryptographic key, you do not have to
manually configure each form with the correct key, and you do not need to use Briefcase
to decrypt the data. It can also be more secure in many cases, because cryptographic keys
are files that must be stored digitally and can be difficult to secure properly. Conversely, a
passphrase can be memorized, saved in a password manager, or written down and physically
secured.
If you already have familiarity with the encryption in Aggregate, or you cannot at all trust
the security of Central itself due to where it has been installed, you may prefer to use
self-supplied key encryption.

8.5.3 Using Self-Supplied Key Encryption

To use self-supplied key encryption, please see the Encrypted Forms document.
When using a self-supplied key with Central, you may and must apply encryption to each
form in a project individually. The encrypted data will not be available over OData or for
download as a ZIP file. You will need to use Briefcase to retrieve and decrypt encrypted
submissions.

8.5.4 Using Project Managed Encryption

For Aggregate users already using encryption

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 225
Chapter 8. Using ODK Central

Central will always respect any encryption settings already present in your Forms. This
means that if you have already put <submission base64RsaPublicKey="…"/> configuration
in your Forms, Central managed encryption will ignore those Forms and you will not be able
to decrypt Submissions uploaded to those Forms using your managed encryption passphrase.
Perhaps this is something you want to have happen, but if not you should remove encryption
configuration from your Forms before turning managed encryption on.

Managed encryption can be enabled only at the Project level. To enable managed encryption,
first navigate to the Project, then to the Settings tab underneath the Project name. On the
right side, you will find the section managing your encryption settings.

To enable managed encryption for the whole project, first click on the Enable Encryption
button. You will be presented with some warnings, which we have also described above in
this document:

226 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.5. Encrypted Forms in Central

Once you review those warnings and press Next to proceed, you will be asked for your
passphrase, and an optional passphrase hint:

The passphrase you provide is the encryption secret that will be used to secure your data.
Anybody who has it will be able to decrypt your submission data. If you lose it, there is no
way to recover it, and no way to decrypt your data. Central does not store your passphrase

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 227
Chapter 8. Using ODK Central

in any way.
The passphrase hint will be displayed whenever the passphrase is needed to decrypt data.
It can be a useful way to store information like where in a shared password manager to look
for the passphrase. It is optional.
Once you have provided a passphrase and ensured that it is correct, press Next to proceed.
At this time, managed encryption will be turned on for the Project. All Forms within the
Project will be updated to include encryption information, and mobile devices will have to
fetch these new versions in order to submit successfully to Central.
Once encrypted data has been submitted, the Download button on the Form Submissions
page will no longer directly download the data. Instead, you will be asked for your encryption
passphrase:

Enter your passphrase and press Download to download the data. If the passphrase you
provide is incorrect, an error message will be displayed after a moment.

8.6 Server Audit Logs in Central

As of version 0.6, ODK Central tracks and logs audit actions for most administrative actions
performed on the server. The following actions are logged:
• Web User Actions
– Create
– Update Details (display name, email, password)
– Assign Role
– Revoke Role
– Retire

228 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.6. Server Audit Logs in Central

• Project Actions
– Create
– Update Details (name, settings, archival)
• Form Actions
– Create
– Update Details (state, settings)
– Update Attachments
– Delete
To access the audit logs, navigate to System, then select Server Audit Logs from the naviga-
tion menu that appears:

Some details will sometimes appear in the Details column. The details view will be improved
in future versions.
The table always defaults to only showing audit events from the current calendar day. To
select a different date range, click on the date in the filter bar. A calendar will appear:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 229
Chapter 8. Using ODK Central

You can click on two separate days to select a range of those days, or you can select a single
day by clicking on it twice. Dates and times are always filtered and displayed according to
the local time on the computer you are browsing the administration panel from.
You can also filter by the type of audit action instead. To do this, click on the dropdown to
the left of the date, which by default is labeled (All Actions).

You can select a single action to filter by, or you can filter by an entire category (select Form
Actions to see any action that pertains to Forms, for example.

8.7 Using the ODK Central REST API

We provide a fully featured REST API for ODK Central. In fact, everything the Central
management website does is over the REST API, so everything it can do you can, too:
creating users and forms, managing app users, and so on. We also provide compliant standard
APIs for OpenRosa and OData.

230 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
8.7. Using the ODK Central REST API

For more information on using the ODK Central APIs, please visit our developer documen-
tation.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 231
Chapter 8. Using ODK Central

232 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

NINE

INTRO TO FORMS IN ODK

Forms used in the ODK ecosystem are XML documents following the ODK XForms spec-
ification, a subset of the W3C XForms specification. (Example XForms are available for
reference.)
Most ODK tools use the ODK JavaRosa library to render forms. Form transfer between
ODK components is governed by the OpenRosa API.
Because of the complexity of the XForms format, we do not recommend coding XForms
directly in XML. The recommended process is:
1. Begin with one of the Form Building Tools.
2. Edit the XML only if necessary.
• Before editing an XForm directly, you need to be familiar with the ODK XForm
specification.
3. Use ODK Validate to check that the edited XForm is well-formed and fully compliant.

9.1 Excel-based form creation

Most ODK users design their forms in Excel using XLSForm.

9.2 Drag-and-drop form creation

For simple forms, ODK Build is a drag-and-drop form designer that works both online and
offline.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 233
Chapter 9. Intro to Forms in ODK

234 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TEN

XLSFORM

XLSForm is a form standard created to help simplify the authoring of forms in Excel.
XLSForms are simple to get started with but allow for the authoring of complex forms.
Forms designed with Excel can be converted to XForms that can be used with ODK tools.
To design your form, refer to the XLSForm form design documentation. Once the form has
been designed, use XLSForm Online, XLSForm Offline, or if you are comfortable on the
command line, pyxform.

10.1 XLSForm Online

We recommend starting with XLSForm Online converter because it is always up-to-date and
allows you to preview what the form will look like.
Use XLSForm Online.

10.2 XLSForm Offline

XLSForm Offline converter is a great option for users who do not have a reliable connection
or may need to design forms offline.
Download XLSForm Offline.

Tip: There is a validation option in the XLSForm Offline that requires Java. To enable
this option, download and install Java and ensure Java is in your PATH. See How do I set
or change the PATH for more.

Note: Your anti-virus may report that XLSForm Offline has a virus. This is a false positive
that is triggered because virus writers sometimes use the same components we use. You can

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 235
Chapter 10. XLSForm

confirm the safety of XLSForm Offline by using the free and unbiased VirusTotal. You may
also use XLSForm Online as an alternative.
On macOS 10.7 or later, you may get a dialog on startup warning you that the XLSForm
Offline is from an unidentified developer. Control-click or right click the icon of the app to
bypass this dialog. See About Gatekeeper for more.

10.3 pyxform

pyxform is a Python library used as a library in XLSForm Online and XLSForm Offline.
For those who want to convert forms at the command line, pyxform can be installed directly
from the command line using pip:

$ pip install pyxform

The xls2xform command can then be used:

$ xls2xform path_to_XLSForm output_path

Tip: Use pyxform together with adb to quickly convert an XLSForm and load it to a
device’s Collect directory. Once you have both tools installed, convert and push in a single
line:

$ xls2xform form-name.xlsx form-name.xml && adb push form-name.xml <collect-


,→directory>/forms/form-name.xml

236 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

ELEVEN

QUESTION TYPES

ODK Collect supports forms with a wide variety of question types. The exact functionality
and display style of each question are specified in your XLSForm definition using the type
and appearance columns.

• Text widgets
• Number widgets
• Date and time widgets
• Select widgets
• Rank widget
• Location widgets
• Image widgets
• Audio widget
• Video widgets
• File upload widget
• Barcode widget
• Range widgets
• Note widget
• URL widget
• Printer widget
• Trigger/acknowledge widget
• Signature widget
• Hidden questions

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 237
Chapter 11. Question Types

• Grouping multiple widgets on the same screen

Tip: You can find an XLSForm with all available question types here.
For simpler forms you can use ODK Build, which provides a visual, drag-and-drop interface.

Helpful terminology
question A prompt to the user, usually requesting a response. Questions are written as a
single line in an XLSForm, and usually appear on a single screen in Collect.
widget A rendered question screen in Collect. The type and appearance of a question
determine the widget that is displayed.

11.1 Text widgets

All of the text widgets share the text type, and the inputs from them are saved as literal
strings.

Warning: If you are using Aggregate and expect answers to be more than 255 charac-
ters, you should increase the database field length to over 255 characters.

• Default text widget


• Number text widget
• External app widget

11.1.1 Default text widget

type text
appearance none
A simple text input.
The text entry field expands as the user types, and line breaks can be included. The keyboard
displayed depends on the Android device and user settings.

238 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.1. Text widgets

XLSForm

Table 11.1: survey


type name label appearance
text name What is your name?

11.1.2 Number text widget

type text
appearance numbers
A numerical input that treats the input as a string, rather than a number.
The number input accepts numerals (0123456789), hyphens (-), and decimal points (.).
These are the only characters available on the number keypad displayed with this widget.
This is useful for phone numbers, ID numbers, IP addresses, and similar data. It can also
be used in place of the Integer widget or Decimal widget if large numbers are needed. (The
integer widget has a limit of nine digits, and the decimal widget has a limit of 15 characters.)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 239
Chapter 11. Question Types

XLSForm

Table 11.2: survey


type name label appear- hint
ance
text string_number_widget
String number numbers text type with numbers ap-
widget pearance

Note: This appearance can be combined with the thousands-sep appearance.

11.1.3 External app widget

type text
appearance ex.*
Launches an external app and receives a string input back from the external app. If the
specified external app is not available, a manual input is prompted.

240 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.1. Text widgets

The external app widget is displayed when the appearance attribute begins with ex:. The
rest of the appearance string specifies the application to launch.
See also:
Launching External Apps

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 241
Chapter 11. Question Types

XLSForm

Table 11.3: survey


type name label appearance hint
text ex_string_widget
Ex ex:change.uw.android.BREATHCOUNT
text type with
string ex:change.uw.android.BREATHCOUNT
widget appearance (can use other external apps)

11.2 Number widgets

Number widgets collect and store number inputs — either integers or floating-point decimals.
Number values can also be captured by the Range widgets.

• Integer widget
• Decimal widget
• Number widget appearance options

242 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.2. Number widgets

– Thousands separator
– Number from an external app

11.2.1 Integer widget

type integer
appearance none
A whole number entry input.
Integer widgets will not accept decimal points, and the entry field has a limit of nine digits.
If you need numbers larger than nine digits, see the Number text widget.
The integer widget supports:
• Thousands separators
• External apps

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 243
Chapter 11. Question Types

XLSForm

Table 11.4: survey


type name label
integer age What is your age in years?

11.2.2 Decimal widget

type decimal
appearance none
A numeric input that will accept decimal points.
Decimal number entry is capped at 15 characters (14 digits and a decimal point). If you
need numbers larger than 15 digits, see the Number text widget.
The decimal widget supports:
• Thousands separators
• External apps

244 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.2. Number widgets

XLSForm

Table 11.5: survey


type name label
decimal weight Weight in kilograms.

11.2.3 Number widget appearance options

Thousands separator

type integer, decimal, (text)


appearance thousands-sep, (numbers)
If thousands-sep is added to appearance, integer, decimal, and number text widgets will
display their values using locale-specific thousands separators.

Note: For locales that use the point separator (.), a space is used instead.

Fig. 11.1: The comma separator, used in English/U.S. (and others).

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 245
Chapter 11. Question Types

Fig. 11.2: The space separator, used in Français/France (and others).

246 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.2. Number widgets

Number from an external app

type integer, decimal


appearance ex:*
By specifying an external app in the appearance, your form can launches an external app
and receive a number (integer or decimal) from the external app as input. If the specified
external app is not available, a manual input is prompted.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 247
Chapter 11. Question Types

XLSForm

Table 11.6: survey


type name label appearance hint
in- ex_integer_widget
Ex ex:change.uw.android.BREATHCOUNT
integer type with
te- integer ex:change.uw.android.BREATHCOUNT
ger widget appearance (can use other external apps)

See also:
Launching External Apps

11.3 Date and time widgets

• Default date widget


– Date widget with spinner input

248 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

– Month and year only


– Year only
• Date widgets with non-Gregorian calendars
– Coptic calendar
– Ethiopian calendar
– Islamic calendar
– Bikram Sambat calendar
– Myanmar calendar
– Persian calendar
• Time widget
• Datetime widget

11.3.1 Default date widget

type date
appearance none

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 249
Chapter 11. Question Types

250 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

XLSForm

Table 11.7: survey


type name label hint
date date_widget Date widget date type with no appearance

Date widget with spinner input

type date
appearance no-calendar
The no-calendar appearance displays a spinner-style date selection. This is especially appro-
priate for selecting dates more than one year in the past or future.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 251
Chapter 11. Question Types

XLSForm

Table 11.8: survey


type name label appear- hint
ance
date date_widget_nocalendar
Date Wid- no- date type with no-calendar ap-
get calendar pearance

Month and year only

type date
appearance month-year
Collects only a month and year.

252 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

XLSForm

Table 11.9: survey


type name label appear- hint
ance
date date_widget_month_year
Date wid- month- date type with month-year ap-
get year pearance

Year only

type date
appearance year
Collects only a year.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 253
Chapter 11. Question Types

XLSForm

Table 11.10: survey


type name label appearance hint
date date_widget_year Date widget year date type with year appearance

11.3.2 Date widgets with non-Gregorian calendars

Collect supports several non-Gregorian calendars.

• Coptic calendar
• Ethiopian calendar
• Islamic calendar
• Bikram Sambat calendar
• Myanmar calendar

254 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

• Persian calendar

Note: The non-Gregorian calendar is used only on input. The dates are converted and
stored as standard Gregorian dates

Coptic calendar

type date
appearance coptic

Ethiopian calendar

type date
appearance ethiopian

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 255
Chapter 11. Question Types

Islamic calendar

type date
appearance islamic

256 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

Bikram Sambat calendar

type date
appearance bikram-sambat

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 257
Chapter 11. Question Types

Myanmar calendar

type date
appearance myanmar

258 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

Persian calendar

type date
appearance persian

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 259
Chapter 11. Question Types

11.3.3 Time widget

type time
appearance none
A time selector. Captures only a specific time-of-day, not a date and time. For date and
time, see the Datetime widget.
The time widget does not accept any appearance attributes.

Note: The time widget stores the time along with a time zone. This can cause unexpected
behavior around Daylight saving time.
For example, if you record a time before the clock change, and then view the time after the
clock change, it will appear to be an hour off. This happens because the recorded time data
is understood as a specific moment in time that is being ”translated” into your current, local
time zone.
A similar problem occurs when moving between geographic time zones.
This makes the time widget unsuitable for abstract time-of-day questions such as What time
do you usually wake up? For questions like this, you may want to use a Select widget with
modal menu. You can set the options at whatever level of accuracy you need — for example,

260 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

15 or 30 minute increments. Alternatively, you could use the select widget for hours, and an
Integer widget for minutes.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 261
Chapter 11. Question Types

262 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

XLSForm

Table 11.11: survey


type name label
time wakeup What time do you usually wakeup?

11.3.4 Datetime widget

A date and time selector.


For date only, see Default date widget. For time only, see Time widget.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 263
Chapter 11. Question Types

264 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.3. Date and time widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 265
Chapter 11. Question Types

XLSForm

Table 11.12: survey


type name label
dateTime previous_meal When was the last time you ate?

Note: The Datetime widget supports the no-calendar spinner-style appearance.

11.4 Select widgets

Select widgets offer the participant options to pick from. You can offer the participant a
single choice, or the ability to choose multiple answers. The order of the choices can be
randomized for any of the select types described below.
The options for a select question are listed on a sheet named choices, in your XLSForm file.
The choices sheet has at least three columns:
list_name A set of choices for a single question share a common list_name. The value of
list_name is included in the type column on the survey sheet.
name The canonical identifier for a specific choice. This value is what is stored on the
completed form. If you refer to a select response using a variable, the name string is
returned.
As with the survey sheet, name must not include spaces.
label The user-facing text displayed for the choice.
Select widgets can include images as choices.

• Single select widget


– Select widget with modal menu
– Select widget with autoadvance
– Select widget with autocomplete
– Select widget with image choices
– Likert widget
– Select widget with compact image options

266 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

– Select widget with width-specified images


– Compact select widget with autoadvance
– Compact select widget with specified width and autoadvance
• Multi select widget
• Image map select widget
• Including media files in choices
• Randomizing choice order
• Including ”other” as a choice

11.4.1 Single select widget

type select_one {list_name}

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 267
Chapter 11. Question Types

XLSForm

Table 11.13: survey


type name label hint
select_one se- Select one select_one type with no appearance, 4
opt_abcd lect_one_widgetwidget text choices

Table 11.14: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Select widget with modal menu

type select_one {list_name}


appearance minimal
Adding the minimal appearance attribute places the choices into a modal overlay menu.

268 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

XLSForm

Table 11.15: survey


type name label ap- hint
pear-
ance
select_one spin- Spinner mini- select_one type with minimal appear-
opt_abcd ner_widget widget mal ance, 4 text choices

Table 11.16: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Note: In web rendered form views (such as Enketo form viewer) a select widget with
minimal appearance will appear in a drop-down (select) menu.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 269
Chapter 11. Question Types

Select widget with autoadvance

type select_one {list_name}


appearance autoadvance
When the autoadvance appearance is added, the form advances immediately to the next
question once a selection is made.
Video showing auto-advance after the questions are answered.

XLSForm

Table 11.17: survey


type name label ap- hint
pear-
ance
select_one se- Select one au- quick select_one type with quick
opt_abcd lect_one_autoadvance_widget
toadvance wid- appearance, 4 text choices
get

Table 11.18: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Select widget with autocomplete

type select_one {list_name}


appearance autocomplete
The autocomplete appearance adds autocomplete to the search and filter feature. This is
especially helpful for questions with a large number of choices.

270 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 271
Chapter 11. Question Types

XLSForm

Table 11.19: survey


type name label ap- hint
pear-
ance
select_one se- Select one auto- select_one type with autocom-
opt_abcd lect_one_autocomplete_widget
search com- plete appearance, 4 text choices
widget plete

Table 11.20: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Select widget with image choices

type select_one {list_name}


appearance none
Select widgets support image choices. The images are referenced in the choices sheet, and
the image files need to be included in the media folder.
See Including media files in choices to learn more about including images in surveys.

272 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

XLSForm

Table 11.21: survey


type name label ap- hint
pear-
ance
select_one grid_widget
Grid select select_one type with no appearance, 4 im-
abcd_icon one widget age choices (a.jpg, b.jpg, c.jpg, d.jpg)

Table 11.22: choices


list_name name label media::image
abcd_icon a A a.jpg
abcd_icon b B b.jpg
abcd_icon c C c.jpg
abcd_icon d D d.jpg

Likert widget

New in version 1.25: ODK Collect v1.25.0

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 273
Chapter 11. Question Types

type select_one {list_name}


appearance likert
A single-select question can be styled as a Likert scale. Options can include text, images or
both. If both are provided, images appear above text.
If adding images, note that the images are referenced in the choices sheet, and the image
files need to be included in the media folder. See Including media files in choices to learn
more about including images in choices.

XLSForm

Table 11.23: survey


type name label ap- hint
pear-
ance
se- lik- Lik- lik- select_one type with Likert appearance, 5 image
lect_one ert_widget
ert ert choices (strongly_disagree.jpg, disagree.jpg, neutral.jpg,
likert Wid- agree.jpg, strongly_agree.jpg)
get

274 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

Table 11.24: choices


list_name name label media::image
likert_widget strongly_disagree Strongly Disagree strongly_disagree.jpg
likert_widget disagree Disagree disagree.jpg
likert_widget neutral Neutral neutral.jpg
likert_widget agree Agree agree.jpg
likert_widget strongly_agree Strongly Agree strongly_agree.jpg

Select widget with compact image options

type select_one {list_name}


appearance compact
When the compact appearance is added, the answer choices display in a single line.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 275
Chapter 11. Question Types

XLSForm

Table 11.25: survey


type name label ap- hint
pear-
ance
select_one grid_widget_compact
Grid select com- select_one type with compact appear-
abcd_icon one widget pact ance, 4 image choices (a.jpg, b.jpg, c.jpg,
d.jpg)

Table 11.26: choices


list_name name label media::image
abcd_icon a A a.jpg
abcd_icon b B b.jpg
abcd_icon c C c.jpg
abcd_icon d D d.jpg

Select widget with width-specified images

type select_one {list_name}


appearance compact-{x}
With the compact-{x} appearance, you can specify the number of images to display on each
row.
For example, to display two images on each row, specify an appearance of compact-2.

276 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

XLSForm

Table 11.27: survey


type name label ap- hint
pear-
ance
se- grid_widget_compact2
Grid select compact-select_one type with compact-2 appear-
lect_one one widget 2 ance, 4 image choices (a.jpg, b.jpg, c.jpg,
abcd_icon d.jpg)

Table 11.28: choices


list_name name label media::image
abcd_icon a A a.jpg
abcd_icon b B b.jpg
abcd_icon c C c.jpg
abcd_icon d D d.jpg

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 277
Chapter 11. Question Types

Compact select widget with autoadvance

type select_one {list_name}


appearance quickcompact
The quickcompact appearance adds autoadvance functionality to the design of the Select
widget with compact image options.
Video showing Compact single select widget and auto-advance after the question is answered.

XLSForm

Table 11.29: survey


type name label ap- hint
pear-
ance
se- grid_widget_quickcompact
Grid se- quick- select_one type with quickcompact ap-
lect_one lect one com- pearance, 4 image choices (a.jpg, b.jpg,
abcd_icon widget pact c.jpg, d.jpg)

Table 11.30: choices


list_name name label media::image
abcd_icon a A a.jpg
abcd_icon b B b.jpg
abcd_icon c C c.jpg
abcd_icon d D d.jpg

Compact select widget with specified width and autoadvance

type select_one {list_name}


appearance quickcompact-{x}
As with compact, you can specify a width when using quickcompact.
For example, to display two images on each row, set the appearance attribute to
quickcompact-2.
Video showing Compact-2 widget and auto-advance after the question is answered.

278 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

XLSForm

Table 11.31: survey


type name label ap- hint
pear-
ance
se- grid_widget_quickcompact2
Grid quickcompact-
select_one type with quickcompact-2 ap-
lect_one select one 2 pearance, 4 image choices (a.jpg, b.jpg,
abcd_icon widget c.jpg, d.jpg)

Table 11.32: choices


list_name name label media::image
abcd_icon a A a.jpg
abcd_icon b B b.jpg
abcd_icon c C c.jpg
abcd_icon d D d.jpg

11.4.2 Multi select widget

type select_multiple {list_name}


appearance none
Multi select questions support multiple answers.

Note: The multi select widget supports many of the same appearance attributes as the
Single select widget:
• minimal appearance
• compact appearance with images
• width-specified compact appearance with images

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 279
Chapter 11. Question Types

XLSForm

Table 11.33: survey


type name label hint
select_multiple se- Multi select select_multiple type with no appear-
opt_abcd lect_multi_widget
widget ance, 4 text choices

Table 11.34: choices


list_name name label media::image
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Warning: If you are using Aggregate and expect users to select many options, you may
need to increase the database field length to over 255 characters.

280 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

11.4.3 Image map select widget

New in version 1.13.


type select_one {list_name}, select_multiple {list-name}
appearance image-map
The image map widget displays an SVG image with selectable regions.
To make an image with selectable regions:
1. Create or edit an .svg source file. Include id attributes on any elements you want to
be selectable.
2. In the choices tab of your XLSForm, put the value of the id attributes in the name
column. Add an appropriate human-friendly label to each choice.
3. In the survey tab of your XLSForm, put the .svg file name in the image column.
4. Include the .svg file in your form’s media folder.
See also:
Inkscape An open source vector graphics editor.
SVG Documentation From Mozilla Developer Network.
Free SVG Files From Wikimedia Commons.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 281
Chapter 11. Question Types

282 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

SVG

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg=


,→"http://www.w3.org/2000/svg">

<title>shapes</title>
<g>
<title>Layer 1</title>
<path id="path" fill="#000080" stroke="#000000" stroke-width="5" d="m125,
,→382c33,56 -193,97 48,55c241,-42 279,-15 241,-62c-38,-47 -13,-42 -106,-40c-93,2␣

,→-183,47 -183,47z"/>

<rect id="rect" fill="#FF0000" stroke="#000000" stroke-width="5" x="52" y="53


,→" width="176" height="149"/>

<ellipse id="ellipse" fill="#41A317" stroke="#000000" stroke-width="5" cx=


,→"423" cy="143" rx="107" ry="78"/>

</g>
</svg>

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 283
Chapter 11. Question Types

XLSForm

Table 11.35: survey


type name label appearance image
select_one shapes choose-shape Choose a shape image- shapes.svg
map
select_multiple choose- Choose multiple image- shapes.svg
shapes shapes shapes map

Table 11.36: choices


list_name name label
shapes path blob
shapes rect rectangle
shapes ellipse ellipse

11.4.4 Including media files in choices

As with questions themselves, choices can include media (image, video, or audio files):

Table 11.37: choices


list_name name label media::image media::video media::audio
opt_media a A a.jpg
opt_media b B b.mp4
opt_media c C c.mp3

Note: select_one and select_multiple questions using the compact appearances will
not display media buttons next to choices. However, if a choice has audio, it will be played
when the choice is selected.

11.4.5 Randomizing choice order

Note: Randomizing choice order support was added in Collect v1.18.2 and Aggregate
v1.7.1. Form conversion requires XLSForm Online � v1.2.2, XLSForm Offline � v1.7.1, or
pyxform � v0.11.6.

284 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.4. Select widgets

To reduce bias, choice order can be randomized for any of the select question types described
above. To display the choices in a different order each time the question is displayed, set
randomize to true in the parameters column of the XLSForm survey sheet:

XLSForm

Table 11.38: survey


type parameters name label
select_one random- se- Select one with random choice order
opt_abcd ize=true lect_one_random_widget
set on each display

Table 11.39: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

In the example above, each time the question is displayed, the choices will be in a different
order. It is often preferable to pick one order that the choices will always be displayed in for a
given filled form. This can be accomplished by setting an integer seed for the randomization.

XLSForm

Table 11.40: survey


type parameters name label calculation
calculate my_seed once(substr(decimal-
date-time(now()),
10))
se- random- se- Select one with random
lect_one ize=true,seed=${my_seed}
lect_one_widget
choice order set once per
opt_abcd filled form

Table 11.41: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 285
Chapter 11. Question Types

This seed can also be used to recreate the order choices were displayed in. See the XForms
spec for a description of the randomization algorithm used.

Note: In the example above, the integer seed is created from the last 8 numbers of the
decimal-date-time() which is unlikely to repeat across devices. In the seed expression,
once() is important because it makes sure the seed is not changed if the same filled form is
opened more than once.

11.4.6 Including ”other” as a choice

On the survey sheet, in the type column, after the type and the list_name, you can add
or_other. This will add ”Other” as an additional option to your choice list. The name value
of the choice when selected will be other.

11.5 Rank widget

The rank widget allows the user to order options from a list. The value saved in the form
and sent to the server is a space-separated ordered list of the options.
Like with Select widgets, the options are listed on a sheet named choices in an XLSForm.
To change the order of the options in the list, tap the Rank items button. In the resulting
dialog, long press on an item and once it gets a border around it, drag it up or down to
change the order. If no default is provided, the value for the question is blank until the user
taps OK in the ranking dialog.
type rank {list_name}

286 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.5. Rank widget

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 287
Chapter 11. Question Types

XLSForm

Table 11.42: survey


type name label hint
rank rank_widget Rank wid- rank type with no appearance, 4 text
opt_abcd get choices

Table 11.43: choices


list_name name label
opt_abcd a A
opt_abcd b B
opt_abcd c C
opt_abcd d D

11.6 Location widgets

Location widgets capture one or more points representing locations on Earth. Each point
is represented as four numbers separated by spaces: latitude, longitude, altitude in meters,

288 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

and accuracy radius in meters.


For example, if a Collect user captured a point while at the coordinates 12°22’17.0”N
1°31’10.9”W, with a reported accuracy radius of 17.4 meters, and at 305 meters above sea
level, the geopoint representation would be:
12.371400 -1.519700 305 17.4
Multiple points that form lines or shapes are separated by semicolons.

Note: The accuracy radius is an estimate of what Android calls the radius of 68% con-
fidence: there is a 68% chance that the true location falls within this radius. This is only
an estimate reported by the Android system based on the available sensors (GPS, network,
etc). The accuracy radius itself may be more or less reliable depending on the sensor(s) used
and current conditions.

• Geopoint widget
– Geopoint with map display
– Geopoint with user-selected location
• Geotrace widget
• Geoshape
– Calculating the area of a geoshape
• Bearing widget
• OpenMapKit widget

11.6.1 Geopoint widget

type geopoint
appearance none
Captures the current geolocation from the device.
For a geopoint with a user-selected location, see Geopoint with user-selected location

Tip: New in version 1.15.


While determining the current coordinates, you will see a dialog box displaying:
• Number of satellites found

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 289
Chapter 11. Question Types

• Elapsed time
To get an accurate fix on your location, the device must find at least four (4) satellites. If
the device can not find at least four satellites, make sure there is nothing obstructing the
device’s view of the sky.
If you have problems with the geopoint widget, be sure to note the elapsed time and accuracy
(if applicable), so that you can share it with your support staff or with the ODK Forum.

XLSForm

Table 11.44: survey


type name label hint
geopoint geopoint_widget Geopoint widget geopoint type with no appearance

Geopoint with map display

type geopoint
appearance maps

290 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

The default Geopoint widget does not display a map to the user. When the appearance
attribute is maps, the widget displays a map to help the user get oriented and confirm that
the selected point is correct and sufficiently accurate.
When the device’s geolocation is available, it is displayed on the map by a blue cross. A blue
shaded circle around the cross represents the accuracy radius of the geolocation. The ”add
marker” button at the top right of the screen can be tapped to add a point at the location
indicated by the middle of the blue cross. The selected point is represented by a small circle
with a red outline.
When the map view is opened again with a selected point, the map is centered on that point.
To change the selection, first tap the ”trash” icon and then select a new point.
For a geopoint with a location that the user can manually select or adjust, see Geopoint with
user-selected location.

XLSForm

Table 11.45: survey


type name label appear- hint
ance
geo- geo- Geopoint maps geopoint type with maps ap-
point point_widget_maps widget pearance

Geopoint with user-selected location

type geopoint
appearance placement-map
The default Geopoint widget does not allow the user to place the point anywhere other than
the device’s current geolocation.
A geopoint with the appearance attribute placement-map allows the user to select any point
from a map. The user can either long press to place the point anywhere, or, if the device
knows its geolocation, tap on the ”add point” button at the top right of the screen. The
selected point is represented by a small circle with a red outline (see arrow in screenshot).
The save button saves the selected point and returns to the question screen. If the point was
selected by long pressing, the accuracy radius and altitude will both be 0. If the device’s
geolocation was selected, the accuracy radius will be greater than 0.
When the map view is opened again with an existing point, the map is centered on the
selected point. To change the selection, first tap the ”trash” icon and then select a new
point.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 291
Chapter 11. Question Types

XLSForm

Table 11.46: survey


type name label appear- hint
ance
geo- geo- Geopoint placement- geopoint type with placement-
point point_widget_placementmap
widget map map appearance

11.6.2 Geotrace widget

type geotrace
appearance none
A series of points. Identical to geoshape except that the first and last point may be different
and at least 2 points are required.
Points can be entered either by tapping the screen to place each point, or by taking readings
of the device’s geolocation over time. On a map, each coordinate is represented by small
circles with red outlines. These are connected by red lines.

292 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

To collect a geotrace, first select the location-recording mode by tapping the ”add point”
button in the upper right side of the screen. The selected mode will be displayed in the
gray bar at the bottom of the screen. While point collection is ongoing, the ”add marker”
button changes to a ”pause” button. The ”back arrow” button can be used to remove the
last-entered point either when actively collecting points or when paused. Any point can
be manually moved at any time by tapping on it and dragging it. The mode can only be
changed if an existing line is first cleared by tapping the ”trash” button. Recording must be
paused to clear the existing line.

Tip: Points that were entered by tapping or adjusted by dragging will always have an
accuracy radius of 0. Points that were read from the device location will never have an
accuracy radius of 0.

Once the trace has been saved, the coordinates of its points will be displayed on the question
screen. The trace can be opened for manual editing by tapping to add more points, moving
existing points or deleting the last-added point. After a trace has been saved once, it cannot
be added to in manual or automatic location recording modes.
The three location recording modes are:
Placement by tapping The user taps the device to place points.
Manual location recording The user chooses when to tap the ”record a point” button at
the top of the screen to capture the device geolocation at that moment.
Automatic location recording The user is prompted to select a recording interval and
accuracy requirement. If the accuracy requirement is set to None, points are always
collected at the recording interval. If the accuracy requirement is set to any other
value, a point will only be captured if it meets the requirement. For example, given a
recording interval of 20s and an accuracy requirement of 10m, the app places a point
at the device location every 20s if the location is accurate to 10m or better.

Warning: If you are using Aggregate and you would like to collect more than 5 points
at a time, you should increase the database field length to over 255 characters. Otherwise,
additional points will be lost.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 293
Chapter 11. Question Types

294 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

XLSForm

Table 11.47: survey


type name label
geotrace trace_example Where have you been?

11.6.3 Geoshape

type geoshape
appearance none
A series of points that form a closed polygon. Identical to geotrace except that the first and
last point are always the same and at least 3 points are required.
Points can be entered either by tapping the screen to place each point, or by taking readings
of the device’s geolocation over time. On a map, each coordinate is represented by small
circles with red outlines. These are connected by red lines.
To collect a geoshape, first select the location-recording mode by tapping the ”add point”
button in the upper right side of the screen. The selected mode will be displayed in the
gray bar at the bottom of the screen. While point collection is ongoing, the ”add marker”
button changes to a ”pause” button. The ”back arrow” button can be used to remove the
last-entered point either when actively collecting points or when paused. Any point can
be manually moved at any time by tapping on it and dragging it. The mode can only be
changed if an existing line is first cleared by tapping the ”trash” button. Recording must be
paused to clear the existing line.

Tip: Points that were entered by tapping or adjusted by dragging will always have an
accuracy radius of 0. Points that were read from the device location will never have an
accuracy radius of 0.

Once the shape has been saved, the coordinates of its points will be displayed on the question
screen. The shape can be opened for manual editing by tapping to add more points, moving
existing points or deleting the last-added point. After a shape has been saved once, it cannot
be added to in manual or automatic location recording modes.
The three location recording modes are:
Placement by tapping The user taps the device to place points.
Manual location recording The user chooses when to tap the ”record a point” button at
the top of the screen to capture the device geolocation at that moment.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 295
Chapter 11. Question Types

Automatic location recording The user is prompted to select a recording interval and
accuracy requirement. If the accuracy requirement is set to None, points are always
collected at the recording interval. If the accuracy requirement is set to any other
value, a point will only be captured if it meets the requirement. For example, given a
recording interval of 20s and an accuracy requirement of 10m, the app places a point
at the device location every 20s if the location is accurate to 10m or better.

Warning: If you are using Aggregate and you would like to collect more than 5 points
at a time, you should increase the database field length to over 255 characters. Otherwise,
additional points will be lost.

296 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

XLSForm

Table 11.48: survey


type name label
geoshape shape_example Select an area

Calculating the area of a geoshape

type calculate
calculation area(${geoshape})
The area() function calculates the land area, in square meters, of a polygon defined in a
Geoshape. The value will be included in your completed survey data, and can also be used
in later widgets in the form.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 297
Chapter 11. Question Types

298 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 299
Chapter 11. Question Types

XLSForm

type name label calculation


geoshape shape Record a Geoshape
calculate shape_area area(${shape})
calculate rounded_shape_area round(${shape_area},
2)
note shape_area_note
The area of the
recorded geoshape
is:

${rounded_shape_area}
m2

11.6.4 Bearing widget

type decimal
appearance bearing
Captures a compass reading, which is stored as a decimal.

300 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.6. Location widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 301
Chapter 11. Question Types

XLSForm

Table 11.49: survey


type name label appear- hint
ance
deci- bear- Bearing wid- bearing decimal type with bearing appear-
mal ing_widget get ance

11.6.5 OpenMapKit widget

OpenMapKit allows you to add questions about OpenStreetMap features in a Collect-


rendered form.
For more details, see the OpenMapKit documentation.

11.7 Image widgets

302 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.7. Image widgets

• Default image widget


– Image widget with annotation
– Image widget with required new image
• Self portrait ( selfie) image widget
• Draw widget
• Scaling down images

11.7.1 Default image widget

type image
appearance none
Captures an image from the device. The user can choose to take a new picture with the
device camera, or select an image from the device photo gallery.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 303
Chapter 11. Question Types

XLSForm

Table 11.50: survey


type name label hint
image image_widget Image widget image type with no appearance

Image widget with annotation

type image
appearance annotate
Adding the annotate appearance allows the user to draw on the image before submitting it.

304 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.7. Image widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 305
Chapter 11. Question Types

306 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.7. Image widgets

XLSForm

Table 11.51: survey


type name label appear- hint
ance
im- anno- Annotate annotate image type with annotate ap-
age tate_image_widget widget pearance

Image widget with required new image

type image
appearance new
An image widget that does not include a Choose Image button. This requires the user to
take a new picture.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 307
Chapter 11. Question Types

XLSForm

type name label ap- hint


pear-
ance
im- im- Image wid- new image type with new appearance (can also be
age age_widget_no_choose
get without added with annotate appearance and on audio
Choose button and video types)

11.7.2 Self portrait (selfie) image widget

type image
appearance new-front
Takes a picture using the front-facing (”selfie”) camera. The Choose image button is not
displayed.
Changed in version 1.15: Prior to v1.15, the appearance attribute for this was selfie. The
old appearance attribute will continue to work on existing forms, but new forms should use
the new-front appearance.

308 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.7. Image widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 309
Chapter 11. Question Types

XLSForm

Table 11.52: survey


type name label hint appear-
ance
im- self- Self portrait (selfie) image type with new-front ap- new-
age portrait widget pearance front

11.7.3 Draw widget

type image
appearance draw
Provides the user a drawing pad and collects the drawn image.

310 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.7. Image widgets

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 311
Chapter 11. Question Types

312 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.8. Audio widget

XLSForm

Table 11.53: survey


type name label appear- hint
ance
im- draw_image_widget Draw wid- draw image type with draw appear-
age get ance

11.7.4 Scaling down images

Images created with any of the image widgets described above can be automatically scaled
down on save by using the max-pixels parameter. If the long edge of the image is larger
than the maximum size specified, the image is resized proportionally so that the long edge
matches the provided pixel value. This is useful to reduce the upload size when bandwidth
is limited.
Available in Collect since v1.10.0 and in XLSForm since 7/2018.

XLSForm

In the parameters column, write max-pixels= followed by the desired maximum length of
the long edge in pixels.

Table 11.54: survey


type name label parameters hint
im- my_scaled_image
Scaled im- max- image scaled to a max long edge of
age age pixels=1024 1024 pixels

11.8 Audio widget

Records audio from an external app.

Note: Some Android devices provide a default application for audio recording. Others do
not, and the user will need to install an audio recording app.
There are many apps available for this, including:
• Audio Recorder from Sony
• RecForge II

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 313
Chapter 11. Question Types

Any app that responds to android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION


will be compatible.

XLSForm

Table 11.55: survey


type name label
audio name_pronounce Please record your name.

11.9 Video widgets

• Default video widget


• Self portrait ( selfie) video widget

314 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.9. Video widgets

11.9.1 Default video widget

Records video, using the device camera.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 315
Chapter 11. Question Types

316 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.9. Video widgets

XLSForm

Table 11.56: survey


type name label hint
video blink- Please record a video of yourself blink- Three times is probably suffi-
ing ing. cient.

11.9.2 Self portrait (selfie) video widget

Records video, using the front-facing (”selfie”) camera. The Choose Video button is not
displayed.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 317
Chapter 11. Question Types

318 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.10. File upload widget

XLSForm

Table 11.57: survey


type name label appear- hint
ance
video selfie- Self portrait (selfie) video new- video type with new-front ap-
video widget front pearance

11.10 File upload widget

New in version 1.15: ODK Collect v1.15.0


Uploads any file from the device to the form.

Warning: Users can upload any file type, which includes potentially malicious files.
You should not include this widget unless you trust the people using the form.
Even then, you should take precautions before downloading or opening files.
• Run an antimalware scan.
• Verify the file is a type you expect (such as a .pdf document), and not a potentially
dangerous file (such as .exe or .ini).

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 319
Chapter 11. Question Types

320 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.11. Barcode widget

XLSForm

Table 11.58: survey


type name label
file some-file Select a file to upload.

11.11 Barcode widget

Scans, decodes, and captures the content of a barcode, using the device camera.
The following barcode formats are supported:
• UPC-A
• UPC-E
• EAN-8
• EAN-13
• Code 39
• Code 93
• Code 128
• Codabar
• ITF
• RSS-14
• RSS-Expanded
• QR Code
• Data Matrix
• Aztec (beta)
• PDF 417 (beta)
• MaxiCode

Note: Barcode scanning is built into Collect versions 1.7.0 and greater.
Versions of Collect prior to 1.7.0 require the Barcode Scanner app to be installed.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 321
Chapter 11. Question Types

• Default barcode widget


• Self portrait ( selfie) barcode widget

11.11.1 Default barcode widget

The flash can be used as a light source when scanning barcodes in a poorly lit environment.

322 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.11. Barcode widget

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 323
Chapter 11. Question Types

XLSForm

Table 11.59: survey


type name label
barcode barcode_example Scan any barcode.

11.11.2 Self portrait (selfie) barcode widget

In some cases a front camera may work better. The flash can’t be used in this case.

XLSForm

Table 11.60: survey


type name label appearance
barcode barcode_example Scan any barcode. front

11.12 Range widgets

Range widgets allow the user to select numbers from within a range that is visually repre-
sented as a number line. The parameters of the range widget are defined by start, end, and
step values defined in the parameters column of your XLSForm. The parameter values can
be integers or decimals.

• Default range widget with integers


• Default range widget with decimals
• Vertical range widget
• Range widget with picker
• Range widget with rating

11.12.1 Default range widget with integers

type range
appearance none

324 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.12. Range widgets

If all three parameter values are integers, the input will be stored as an integer.

XLSForm

Table 11.61: survey


type name label ap- hint parameters
pear-
ance
range range_integer_widget
Range inte- range integer widget with start=1;end=10;step=1
ger widget no appearance

11.12.2 Default range widget with decimals

type range
appearance none
If any of the parameter values are decimals, the input will be stored as a decimal.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 325
Chapter 11. Question Types

XLSForm

Table 11.62: survey


type name label ap- hint parameters
pear-
ance
range range_decimal_widget
Range deci- range decimal widget start=1.5;end=5.5;step=0.5
mal widget with no appearance

11.12.3 Vertical range widget

type range
appearance vertical
To display the range widget’s number line vertically, use the vertical appearance. Both
integers and decimals are supported.

326 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.12. Range widgets

XLSForm

Table 11.63: survey


type name label ap- hint parameters
pear-
ance
range range_integer_widget_vertical
Range vertical verti- range integer widget start=1;end=10;step=1
integer widget cal with vertical appear-
ance

11.12.4 Range widget with picker

type range
appearance picker
When the picker appearance is added, the range widget is displayed with a spinner-style
select menu in a dialog. The value between horizontal lines is the selected value. Users can
scroll the spinner up and down or can tap on the value above to go up by one and on the
value below to go down by one.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 327
Chapter 11. Question Types

328 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.12. Range widgets

XLSForm

Table 11.64: survey


type name label ap- hint parameters
pear-
ance
range range_integer_widget_picker
Range picker picker range integer widget start=1;end=10;step=1
integer widget with picker appearance

11.12.5 Range widget with rating

type range
appearance rating
When the rating appearance is added, the range widget is displayed with stars having equal
spacing. Number of stars is calculated using the end parameter. When the user taps on an
empty star, the stars up to and including that star will be filled. If the stars don’t fit in the
device width, they will wrap onto additional lines.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 329
Chapter 11. Question Types

XLSForm

Table 11.65: survey


type name label ap- hint pa-
pear- rame-
ance ters
range range_integer_widget_rating
Range rating rating range integer widget with end=9
widget rating appearance

11.13 Note widget


type note
appearance none
A note to the user, accepting no input. This example includes hint text.

330 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.14. URL widget

XLSForm

type name label hint


note note_1 This is an example note. The text displays, but there is no input.

11.14 URL widget


type text
appearance url
Provides a link which the user can open from the survey. Takes no input.
The URL to open is specified with default.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 331
Chapter 11. Question Types

XLSForm

Table 11.66: survey


type name label ap- hint default
pear-
ance
text url_widget
URL url text type with url appearance and default http:
widget value of http://getodk.org/ //getodk.
org/

11.15 Printer widget


type text
appearance printer:org.opendatakit.sensors.ZebraPrinter
Connects to an external label printer, and prints labels that can contain a barcode, a QR
code, or text.
See printer-widget for complete details.

332 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.16. Trigger/acknowledge widget

XLSForm

Table 11.67: survey


type name label appearance calculation
text ex_printer_widget
Ex printer:org.opendatakit. con-
printer sensors.ZebraPrinter cat(’123456789’,’<br>’,’QR
widget CODE’,’<br>’,’Text’)

11.16 Trigger/acknowledge widget

type trigger, acknowledge


appearance none
The trigger widget, also known as the acknowledge widget, presents a single checkbox.
A completed trigger response is stored as the string OK.
The example shown here includes the required attribute.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 333
Chapter 11. Question Types

334 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.17. Signature widget

XLSForm

Table 11.68: survey


type name label hint re-
quired
trig- my_trigger
Trigger Prompts for confirmation. Useful to combine with re- true()
ger widget quired or relevant. (type=trigger)

11.17 Signature widget


type image
appearance signature
Collects a signature from the user.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 335
Chapter 11. Question Types

336 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.18. Hidden questions

XLSForm

Table 11.69: table


type name label appear- hint
ance
im- signa- Signature wid- signature image type with signature appear-
age ture_widget get ance

11.18 Hidden questions

Not all question types render as visible widgets in Collect. These questions do collect and
store values, which are accessible as variables and available in Aggregate and other data
analysis tools.

• Metadata
• Geolocation at survey start
• Calculate

11.18.1 Metadata

Metadata questions capture information about the device or a survey collection event and
are not visible to the user.
A more complete record of user behavior within a form can be generated by enabling form
audit logging.
These items are dependent on the survey collection event:
• start — The datetime the survey was started in ISO 8601 format (e.g., 2019-09-
27T09:45:10.854-07:00).
• end — The last datetime the survey was saved in ISO 8601 format.
• today — The date the survey was started in ISO 8601 format (e.g, 2019-09-27).
• start-geopoint — The geolocation when the survey was started. Read more.
These items are defined by the device and cannot be changed:
• deviceid
• subscriberid

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 337
Chapter 11. Question Types

• simserial
These items are defined in Collect, and can be edited in Settings:
• username
• phonenumber

XLSForm

Table 11.70: survey


type name
start start
end end
today today
deviceid deviceid
subscriberid subscriberid
simserial simserial
username username
phonenumber phonenumber
start-geopoint start-geopoint

11.18.2 Geolocation at survey start

See also:
Audit log geolocation tracking

Note: Geolocation tracking was added in Collect v1.23 and Aggregate v2.0.4. Form
conversion requires XLSForm Online � v1.6.1, XLSForm Offline � v1.11.1 or pyxform � v0.15.1.

The start-geopoint question type is used to capture a single geolocation in geopoint format
when the survey is first started. Questions of type start-geopoint may be given any allowable
name. Although it is possible to have more than one start-geopoint question in a form, all
will have the same value.
Any time a survey with a start-geopoint question is opened in Collect, the enumerator will
see a warning that the form tracks device location. If the device battery is low, or if location
tracking needs to be turned off for any reason, you can tap � → Track location or turn off
location providers in Android.
The first time that a survey with a start-geopoint question is opened, Collect will attempt
to read the device’s geolocation. The geolocation reading with the highest accuracy received

338 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.19. Grouping multiple widgets on the same screen

in a 20-second window will be recorded. A location icon will be displayed in the Android
status bar while the geolocation is being requested by Collect.
Geolocation is read using data from GPS, WiFi and possibly other signals so this feature
should work in most environments.
If geolocation information is unavailable, the question will be left blank. Reasons for a blank
value may include the enumerator turning off location providers, Collect not having location
permissions, Google Play Services not being installed, the GPS not having satellite lock and
more. No troubleshooting information is provided in the form submission.
Including a start-geopoint question may make it faster to get high-accuracy geolocation
readings for other location question types by ”warming” the GPS.

11.18.3 Calculate

type calculate
Calculate questions let you evaluate complex expressions, storing the values for later use.
For more details, see Calculations.

11.19 Grouping multiple widgets on the same screen

type begin_group
appearance field-list
The field-list appearance attribute, applied to a group of widgets, displays them all on a
single screen.

Warning: Relevance, constraint and calculation evaluation within the same screen is
supported in Collect v1.22 and later.

See also:
Groups of questions and Repeating questions.
Select widgets included in a field-list group can have one of several appearance attributes:
label Only the option labels are displayed, without checkboxes.
list The labels are displayed along with checkboxes for multi-select questions and radio
buttons for single-select questions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 339
Chapter 11. Question Types

list-nolabel Only checkboxes or radio buttons are displayed, without their labels. This is
often used for sets of questions with repeated answer choices.

340 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
11.19. Grouping multiple widgets on the same screen

XLSForm

Table 11.71: survey


type name label ap- hint
pear-
ance
be- ta- List field-
gin_group ble_list_testgroup list
se- ta- Label la-
Show only the labels of these options and not
lect_one ble_list_test_label
widget bel
the inputs (type=select_one yes_no, appear-
yes_no ance=label)
se- ta- Label la- Show only the labels of these options and not
lect_multiple
ble_list_test_label_2
multi bel the inputs (type=select_multiple yes_no, ap-
yes_no widget pearance=label)
se- ta- List list- Show only the inputs of these options
lect_one ble_list_1 widget nolabeland not the labels (type=select_one yes_no,
yes_no appearance=list-nolabel)
se- ta- List list- Show only the inputs of these options and
lect_multiple
ble_list_2 multi nolabelnot the labels (type=select_multiple yes_no,
yes_no widget appearance=list-nolabel)
se- list_widget List list This is a normal list widget with (type = se-
lect_one widget lect_one, appearance = list)
yes_no
se- list_multi_widget
List list This is a normal list widget with (type = se-
lect_multiple multi lect_multiple, appearance = list)
yes_no widget
end_group

Table 11.72: choices


list_name name label
yes_no yes Yes
yes_no no No
yes_no dk Don’t Know
yes_no na Not Applicable

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 341
Chapter 11. Question Types

342 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWELVE

FORM LOGIC

ODK Collect supports a wide range of dynamic form behavior. This document covers how
to specify this behavior in your XLSForm definition.
See also:
XLSForm

Warning: Relevance, constraint and calculation evaluation within the same screen is
supported in Collect v1.22 and later. In earlier versions of Collect, questions tied by logic
must be displayed on different screens.

• Form logic building blocks


– Variables
– Expressions
– Calculations
– Values from the last saved record
– Form logic gotchas
• Requiring responses
• Setting default responses
– Static defaults
– Dynamic defaults
• Validating and restricting responses
– Read-only questions
• Conditionally showing questions

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 343
Chapter 12. Form Logic

– Simple example
– Complex example
• Groups of questions
• Repeating questions
– Controlling the number of repetitions
• Filtering options in select questions

12.1 Form logic building blocks

12.1.1 Variables

Variables reference the value of previously answered questions. To use a variable, put the
question’s name in curly brackets preceded by a dollar sign:
${question-name}
Variables can be used in label, hint, and repeat_count columns, as well as any column that
accepts an expression.

344 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.1. Form logic building blocks

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 345
Chapter 12. Form Logic

XLSForm

Table 12.1: survey


type name label
text your_name What is your name?
note hello_name Hello, ${your_name}.

12.1.2 Expressions

An expression, sometimes called a formula, is evaluated dynamically as a form is filled out. It


can include XPath functions, operators, values from previous responses, and (in some cases)
the value of the current response.

Example expressions

${bill_amount} * 0.18 Multiplies the previous value bill_amount by 18%, to calculate


a suitable tip.
concat(${first_name}, ’ ’, ${last_name}) Concatenates two previous responses with
a space between them into a single string.
${age} >= 18 Evaluates to True or False, depending on the value of age.
round(${bill_amount} * ${tip_percent} * 0.01, 2) Calculates a tip amount based
on two previously entered values, and then rounds the result to two decimal places.
Expressions are used in:
• Calculations
• Validating and restricting responses
• Conditionally showing questions

12.1.3 Calculations

To evaluate complex expressions, use a calculate row. Put the expression to be evaluated in
the calculation column. Then, you can refer to the calculated value using the calculate row’s
name.
Expressions cannot be used in label and hint columns, so if you want to display calculated
values to the user, you must first use a calculate row and then a variable.

346 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.1. Form logic building blocks

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 347
Chapter 12. Form Logic

XLSForm

Table 12.2: survey


type name label calculation
decimal bill_amount Bill amount:
calculate tip_18 round((${bill_amount}
* 0.18),2)
calculate tip_18_total ${bill_amount} +
${tip_18}
note tip_18_note
Bill:
$${bill_amount}
Tip (18%):
$${tip_18}
Total:
$${tip_18_total}

12.1.4 Values from the last saved record

Warning: Support for last-saved was added in Collect v1.21.0. Form conversion requires
XLSForm Online � v2.0.0 or pyxform � v1.0.0. Using older versions will have unpredictable
results.

You can refer to values from the last saved record of this form definition:
${last-saved#question-name}
This can be very useful when an enumerator has to enter the same value for multiple con-
secutive records. An example of this would be entering in the same district for a series of
households.

XLSForm that shows using a last-saved value as a dynamic default

Table 12.3: survey


type name label default
text street Street ${last-saved#street}

348 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.1. Form logic building blocks

The value is pulled from the last saved record. This is often the most recently created record
but it could also be a previously-existing record that was edited and saved. For the first
record ever saved for a form definition, the last saved value for any field will be blank.
Questions of any type can have their defaults set based on the last saved record. References
to the last saved record can be used as part of any expression wherever expressions are
allowed.

12.1.5 Form logic gotchas

When expressions are evaluated

Every expression is constantly re-evaluated as an enumerator progresses through a form.


This is an important mental model to have and can explain sometimes unexpected behavior.
More specifically, expressions are re-evaluated when:
• a form is opened
• the value of any question in the form changes
• a repeat group is added or deleted
• a form is saved or finalized
This is particularly important to remember when using functions that access state outside
of the form such as random() or now(). The value they represent will change over and over
again as an enumerator fills out a form.
The once() function prevents multiple evaluation by only evaluating the expression passed
into it if the node has no value. That means the expression will be evaluated once either on
form open or when any values the expression depends on are set.
Every call on now() in the form will have the same value unless the once() function is used.
For example, the following calculate will keep track of the first time the form was opened:

Table 12.4: survey


type name label calculation
calculate datetime_first_opened once(now())

The following calculate will keep track of the first time the enumerator set a value for the
age question:

Table 12.5: survey


type name label calculation
integer age What is your age?
calculate age_timestamp if(${age} = ”, ”, once(now()))

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 349
Chapter 12. Form Logic

Empty values in math

Unanswered number questions are nil. That is, they have no value. When a variable refer-
encing an empty value is used in a math operator or function, it is treated as Not a Number
(NaN). The empty value will not be converted to zero. The result of a calculation including
NaN will also be NaN, which may not be the behavior you want or expect.
To convert empty values to zero, use either the coalesce() function or the if() function.

coalesce(${potentially_empty_value}, 0)

if(${potentially_empty_value}="", 0, ${potentially_empty_value})

12.2 Requiring responses

By default, users are able to skip questions in a form. To make a question required, put yes
in the required column.
Required questions are marked with a small asterisk to the left of the question label. You
can optionally include a required_message which will be displayed to the user who tries to
advance the form without answering the question.

350 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.3. Setting default responses

XLSForm

Table 12.6: survey


type name label required required_message
text name What is your name? yes Please answer the question.

12.3 Setting default responses

To provide a default response to a question, put a value in the default column. Defaults are
set when a record is first created from a form definition. Defaults can either be fixed values
(static defaults) or the result of some expression (dynamic defaults).

12.3.1 Static defaults

The text in the default column for a question is taken literally as the default value. Quotes
should not be used to wrap values, unless you actually want those quote marks to appear
in the default response value.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 351
Chapter 12. Form Logic

In the example below, the ”Phone call” option with underlying value phone_call will be
selected when the question is first displayed. The enumerator can either keep that selection
or change it.

XLSForm to select ”Phone call” as the default contact method

Table 12.7: survey


type name label default
select_one contacts contact_method How should we contact you? phone_call

Table 12.8: choices


list_name name label
contacts phone_call Phone call
contacts text_message Text message
contacts email Email

12.3.2 Dynamic defaults

Warning: Support for dynamic defaults was added in Collect v1.24.0. Form conversion
requires XLSForm Online � v2.0.0 or pyxform � v1.0.0. Using older versions will have
unpredictable results.

If you put an expression in the default column for a question, that expression will be evaluated
once when a record is first created from a form definition. This allows you to use values
from outside the form like the current date or the server username. Dynamic defaults can’t
be used to set the default value of one field to the value of another field in the form. Learn
about alternatives in the tip below.

XLSForm to set the current date as default

Table 12.9: survey


type name label default
date fever_onset When did the fever start? now()

In the example below, if a username is set either in the server configuration or the metadata
settings, that username will be used as the default for the question asked to the enumerator.

352 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.3. Setting default responses

XLSForm to set the default username as the server username

Table 12.10: survey


type name label default
username username
text confirmed_username What is your username? ${username}

If enumerators will need to enter the same value for multiple consecutive records, dynamic
defaults can be combined with last saved.
Dynamic defaults in repeats are evaluated when a new repeat instance is added.

Tip: You may want to use a value filled out by the enumerator as a default for another
question that the enumerator will later fill in. Dynamic defaults can’t be used for this
because they are evaluated once when a record is first created which is before an enumerator
fills in any data.
One option is to use the calculation column and wrap your default value expression in a
once() function.

XLSForm that uses a child’s current age as the default for diagnosis age

Table 12.11: survey


type name label calculation
text name Child’s name
integer current_age Child’s age
select_one gndr gender Gender
integer malaria_age Age at malaria diagnosis once(${current_age})

This solution has some limitations:


• The value of the calculated default will get set to the first value that the earlier question
receives, even if it is changed before viewing the later question.
Example: In the above form, if you enter 8 on current_age, then advance to gender,
then back up and change current_age to 10, when you get to malaria_age, the default
value will be 8.
• If the first earlier question has a value, the dependent question will also have a value
— once() will evaluate anytime the question’s value is blank.
Example: In the above form, if you enter 8 on current_age and then delete the value 8
when you get to malaria_age (intending to leave it blank) the 8 value will come back

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 353
Chapter 12. Form Logic

as the answer when you advance. (In this case, using a blank value to indicate ”child
does not have malaria” would fail.)

12.4 Validating and restricting responses

To validate or restrict response values, use the constraint column. The constraint expression
will be evaluated when the user advances to the next screen. If the expression evaluates
to True, the form advances as usual. If False, the form does not advance and the con-
straint_message is displayed.
The entered value of the response is represented in the expression with a single dot (.).
Constraint expressions often use comparison operators and regular expressions. For example:
. >= 18 True if response is greater than or equal to 18.
. < 20 and . > 200 True if the response is between 20 and 200.
regex(.,’p{L}+’) True if the response only contains letters, without spaces, separators, or
numbers.
not(contains(., ’prohibited’)) True if the substring prohibited does not appear in the
response.

Note: Constraints are not evaluated if the response is left blank. To restrict empty
responses, make the question required.

See also:
Using regular expressions

354 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.4. Validating and restricting responses

XLSForm

Table 12.12: survey


type name label constraint constraint_message
text mid- What is your middle initial? regex(., Just the first letter.
dle_initial ’p{L}’)

12.4.1 Read-only questions

To completely restrict user-entry, use the read_only column with a value of yes. This
is usually combined with a default response, which is often calculated based on previous
responses.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 355
Chapter 12. Form Logic

XLSForm

Table 12.13: survey


type name label read_only
default calculation
deci- salary_income
Income from
mal salary
deci- self_income
Income from
mal self-employment
deci- other_income
Other income
mal
cal- in- ${salary_income} +
cu- come_sum ${self_income} +
late ${other_income}
deci- to- Total income yes ${in-
mal tal_income come_sum}

12.5 Conditionally showing questions

The relevant column can be used to show or hide questions and groups of questions based
on previous responses.
If the expression in the relevant column evaluates to True, the question or group is shown.
If False, the question is skipped.
Often, comparison operators are used in relevance expressions. For example:
${age} <= 5 True if age is five or less.
${has_children} = ’yes’ True if the answer to has_children was yes.
Relevance expressions can also use functions. For example:
selected(${allergies}, ’peanut’) True if peanut was selected in the Multi select widget
named allergies.
contains(${haystack}, ’needle’) True if the exact string needle is contained anywhere
inside the response to haystack.
count-selected(${toppings}) > 5 True if more than five options were selected in the
Multi select widget named toppings.

356 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.5. Conditionally showing questions

12.5.1 Simple example

XLSForm

Table 12.14: survey


type name label relevant
select_one watch_sports Do you watch sports?
yes_no
text fa- What is your favorite ${watch_sports} =
vorite_team team? ’yes’

Table 12.15: choices


list_name name label
yes_no yes Yes
yes_no no No

12.5.2 Complex example

Video showing a series of select questions. The questions displayed change depending on
what choices are selected in the first questions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 357
Chapter 12. Form Logic

XLSForm

Table 12.16: survey


type name label hint relevant con-
straint
se- what_issues
Have you experi- Select all that
lect_multiple enced any of the apply.
medi- following?
cal_issues
se- what_cancer
What type of Select all that se-
lect_multiple cancer have you apply. lected(${what_issues},
can- experienced? ’cancer’)
cer_types
se- what_diabetes
What type of Select all that se-
lect_multiple diabetes do you apply. lected(${what_issues},
dia- have? ’diabetes’)
betes_types
be- blood_pressure
Blood pressure se-
gin_group reading lected(${what_issues},
’hypertension’)
integer sys- Systolic . > 40
tolic_bp and . <
400
integer dias- Diastolic . >=
tolic_bp 20 and .
<= 200
end_group
text other_health
List other issues. se-
lected(${what_issues},
’other’)
note af- This note is after
ter_health_note
all health ques-
tions.

358 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.6. Groups of questions

Table 12.17: choices


list_name name label
medical_issues cancer Cancer
medical_issues diabetes Diabetes
medical_issues hypertension Hypertension
medical_issues other Other
cancer_types lung Lung cancer
cancer_types skin Skin cancer
cancer_types prostate Prostate cancer
cancer_types breast Breast cancer
cancer_types other Other
diabetes_types type_1 Type 1 (Insulin dependent)
diabetes_types type_2 Type 2 (Insulin resistant)

Warning: Calculations are evaluated regardless of their relevance.


For example, if you have a calculate widget that adds together two previous responses,
you cannot use relevant to skip in the case of missing values. (Missing values will cause
an error.)
Instead, use the if() function to check for the existence of a value, and put your calculation
inside the then argument.
For example, when adding together fields a and b:
if(${a} != '' and ${b} != '', ${a} + ${b}, '')

In context:

type name label calculation


integer a a=
integer b b=
calcu- a_plus_b if(${a} != ” and ${b} != ”, ${a} +
late ${b}, ”)
note dis- a + b =
play_sum ${a_plus_b}

12.6 Groups of questions

To group questions, use the begin_group…end_group syntax.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 359
Chapter 12. Form Logic

XLSForm — Question group

Table 12.18: survey


type name label
begin_group my_group My text widgets
text question_1 Text widget 1
text question_2 These questions will both be grouped together
end_group

If given a label, groups will be visible in the form path to help orient the user (e.g. My text
widgets > Text widget 1). Labeled groups will also be visible as clickable items in the jump
menu:

Warning: If you use ODK Build v0.3.4 or earlier, your groups will not be visible in the
jump menu. The items inside the groups will display as if they weren’t grouped at all.

Groups without labels can be helpful for organizing questions in a way that’s invisible to the
user. This technique can be helpful for internal organization of the form. These groups can
also be a convenient way to conditionally show certain questions.

360 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.7. Repeating questions

12.7 Repeating questions

You can ask the same question or questions multiple times by wrapping them in be-
gin_repeat…end_repeat. By default, enumerators are asked before each repetition whether
they would like to add another repeat. It is also possible to determine the number of repe-
titions ahead of time which can make the user interaction more intuitive. You can also add
repeats as long as a condition is met.

XLSForm — Repeating one or more questions

Table 12.19: survey


type name label
begin_repeat my_repeat repeat group label
note repeated_note All of these questions will be repeated.
text name What is your name?
text quest What is your quest?
text fave_color What is your favorite color?
end_repeat

See also:
Repeat Recipes and Tips describes strategies to address common repetition scenarios.

Tip: Using repetition in a form is very powerful but can also make training and data
analysis more time-consuming. Repeats exported from Central or Briefcase be in their own
files and will need to be joined with their parent records for analysis.
Before adding repeats to your form, consider other options:
• if the number of repetitions is small and known ahead of time, consider ”unrolling” the
repeat by copying the same questions several times.
• if the number of repetitions is large and includes many questions, consider building a
separate form that enumerators fill out multiple times and link the forms with some
parent key (e.g., a household ID).
If repeats are needed, consider adding some summary calculations at the end so that analysis
will not require joining the repeats with their parent records. For example, if you are
gathering household information and would like to compute the total number of households
visited across all enumerators, add a calculation after the repeats that counts the repetitions
in each submission.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 361
Chapter 12. Form Logic

12.7.1 Controlling the number of repetitions

User-controlled repeats

By default, the enumerator controls how many times the questions are repeated.
Before each repetition, the user is asked if they want to add another.

Note: The label in the begin_repeat row is shown in the Add New Group? message.
A meaningful label will help enumerators and participants navigate the form as intended.
This interaction may be confusing to users the first time they see it. If enumerators know
the number of repetitions ahead of time, consider using a dynamically defined repeat count.

Fig. 12.1: The user is given the option to add each repetition.

Tip: The jump menu also provides shortcuts to add or remove repeat instances.

362 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.7. Repeating questions

Fixed repeat count

Use the repeat_count column to define the number of times that questions will repeat.

XLSForm

Table 12.20: survey


type name label re-
peat_count
be- my_repeat Repeat group label 3
gin_repeat
note re- These questions will be repeated exactly three
peated_note times.
text name What is your name?
text quest What is your quest?
text fave_color What is your favorite color?
end_repeat

Dynamically defined repeat count

The repeat_count column can reference previous responses and calculations.

XLSForm

Table 12.21: survey


type name label repeat_count
integer num- How many children do you
ber_of_children have?
be- child_questions Questions about child ${num-
gin_repeat ber_of_children}
text child_name Child’s name
integer child_age Child’s age
end_repeat

Repeating as long as a condition is met

If the enumerator won’t know how many repetitions are needed ahead of time, you can still
avoid the ”Add new group?” dialog by using the answer to a question to decide whether

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 363
Chapter 12. Form Logic

another repeat instance should be added. In the example below, repeated questions about
plants will be asked as long as the user answers ”yes” to the last question.

Table 12.22: survey


type name label calcu- repeat_count
lation
calcu- count count(${plant})
late
be- plant Plant if(${count} = 0 or ${count}${count})
gin_repeat ${plant}[position()=${count}]/more_plants
+1
= ’yes’
text species Species
integer esti- Estimated size
mated_size
se- more_plants
Are there
lect_one more plants in
yes_no this area?
end_repeat

Table 12.23: choices


list_name name label
yes_no yes Yes
yes_no no No

This works by maintaining a count() of the existing repetitions and either making re-
peat_count one more than that if the continuing condition is met or keeping the re-
peat_count the same if the ending condition is met.
In the repeat_count expression, ${count} = 0 ensures that there is always at least one repeat
instance created. The continuing condition is ${plant}[position()=${count}]/more_plants
= ’yes’ which means ”the answer to more_plants was yes the last time it was asked.” The
expression position()=${count} uses the position() function to select the last plant that
was added. Adding /more_plants to the end of that selects the more_plants question.

Repeating zero or more times

Sometimes it only makes sense to collect information represented by the questions in a


repeat under certain conditions. If the number of total repetitions is known ahead of time,
use Dynamically defined repeat count and allow a count of 0. If the count is not known ahead
of time, Conditionally showing questions can be used to represent 0 or more repetitions. In
the example below, questions about trees will only be asked if the user indicates that there
are trees to survey.

364 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
12.8. Filtering options in select questions

Table 12.24: survey


type name label relevant
select_one trees_present Are there any trees in this
yes_no area?
begin_repeat tree Tree ${trees_present} =
’yes’
text species Species
integer esti- Estimated age
mated_age
end_repeat

Table 12.25: choices


list_name name label
yes_no yes Yes
yes_no no No

12.8 Filtering options in select questions

To limit the options in a select question based on the answer to a previous question, use a
choice_filter row in the survey sheet, and filter key columns in the choices sheet.
For example, you might ask the user to select a state first, and then only display cities within
that state. This is called a cascading select, and can be extended to any depth. This example
form shows a three-tiered cascade: state, county, city.

XLSForm

Table 12.26: survey


type name label choice_filter
select_one job_category Job cate-
job_categories gory
select_one job_titles job_title Job title job_category=${job_category}

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 365
Chapter 12. Form Logic

Table 12.27: choices


list_name name label job_category
job_categories finance Finance
job_categories hr Human Resources
job_categories admin Administration/Office
job_categories marketing Marketing
job_titles ar Accounts Receivable finance
job_titles ap Account Payable finance
job_titles bk Bookkeeping finance
job_titles pay Payroll finance
job_titles recruiting Recruiting hr
job_titles training Training hr
job_titles retention Retention hr
job_titles asst Office Assistant admin
job_titles mngr Office Manager admin
job_titles scheduler Scheduler admin
job_titles reception Receptionist admin
job_titles creative_dir Creative Director marketing
job_titles print_design Print Designer marketing
job_titles ad_buyer Ad Buyer marketing
job_titles copywriter Copywriter marketing

366 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTEEN

FORM STYLING

Questions can include Media such as images, sound or video. Additionally, labels, hints, and
choices in an XLSForm can all be styled using Markdown, fonts and colors, and Emoji.

13.1 Media

You can include questions in your form that display images or that play video or audio files
by including a media column in your XLSForm. Files referenced should be included in your
form’s media folder.

13.1.1 Images

Adding an image to a question displays the image as part of the question.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 367
Chapter 13. Form Styling

XLSForm

Table 13.1: survey


type name label media::image
select_one yesnodk coffee Do you want coffee? mug.jpg

Table 13.2: choices


list_name name label
yesnodk y yes
yesnodk n no
yesnodk dk I don’t know

13.1.2 Audio

Adding audio to a question adds a play/stop button that controls the audio clip.

368 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.1. Media

XLSForm

Table 13.3: survey


type name label media::audio
text feel How does this song make you feel? amazing.mp3

13.1.3 Video

Adding video to a question adds a button that will play the video clip full screen when
clicked.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 369
Chapter 13. Form Styling

XLSForm

Table 13.4: survey


type name label media::video
integer people How many people do you see in the video? people.mp4

13.1.4 Autoplaying Media

Audio and video on questions can also be played automatically when a question is viewed
by adding an autoplay column specifying either audio or video.

XLSForm

Table 13.5: survey


type name label media::audio autoplay
text feel How does this song make you feel? amazing.mp3 audio

Some considerations for autoplaying:

370 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.2. Markdown

• Audio/video included in select choices will be autoplayed after the question’s media in
display order
• If using a field-list appearance for a group no media will be autoplayed
• Appearances for selects that hide buttons will disable autoplay for media

13.2 Markdown

XLSForm supports limited used of Markdown.

13.2.1 Headers

Labels and hints can be styled with one of six header levels.

# Header H1

## Header H2

### Header H3

#### Header H4

##### Header H5

###### Header H6

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 371
Chapter 13. Form Styling

Warning: If a Markdown header is used, the label or hint can only be one line of text.
Line breaks in the XLSForm cell will break the header styling.

372 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.2. Markdown

Fig. 13.1: A comparison of headline sizes. This exact effect cannot be produced using Mark-
down.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 373
Chapter 13. Form Styling

XLSForm

Table 13.6: survey


type name label hint
note broken_header
## Attempted H2 ### Attempted
Label Header H3 hint headline,

A line below the Here is some text


headline below the headline.

13.2.2 Emphasis

Collect’s Markdown support also includes bold and italic styling.

374 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.2. Markdown

_italic_

*italic*

__bold__

**bold**

Note: The label of a form widget is already bold, so bolding text within the label has no
effect. Similarly, the hint text of a form widget is already in italics, so italicizing text within
the hint has no effect.

XLSForm

type name hint label


note empha- This label has bold and italic text. This hint has bold and italic text.
sis

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 375
Chapter 13. Form Styling

13.2.3 Hyperlinks

Collect’s Markdown support include hyperlinks, which will open in the device’s default
browser.

[Link anchor text](link.url)

XLSForm

Table 13.7: survey


type name label hint
note hyper- This label [contains a link](http:// This hint [contains a link](http://
link example.com). example.com).

13.2.4 Escaping Markdown

New in version 1.15.


If you want to include literal asterisks or underscores, escape them with a back-slash (\). If
you want to include a literal back-slash, you’ll need to escape that too.

376 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.3. Fonts and colors

XLSForm

type name label hint


note es- # This headline is normal *Asterisks* and _underscores_ and one
cape_md sized slash: \

13.2.5 Inline HTML

Many Markdown implementations support inline HTML, but Collect only supports a small
subset of HTML elements. Support of HTML is further limited because:
• Your exact Android device, operating system version, and other device-related factors
will affect what HTML can be rendered, and how it is rendered.
• HTML is not supported by other form rendering tools in the XForms ecosystem. For
example, HTML elements that work in Collect may not work in Enketo.
For these reasons, we do not recommend using HTML in forms (except the <span> element
noted below).
See also:
The list of HTML tags currently supported in Collect.

13.3 Fonts and colors

To add custom styling to hint, label, and choice labels, use the style attribute on a span tag.
The style attribute accepts CSS-like key-value pairs for setting color and font-family.
• For color, try one of the named HTML color values or use a hex color.
• For font-family, it is best to use generic font categories rather than specific fonts:
– serif
– sans-serif
– monospace
– cursive
– fantasy
This will ensure support across most devices. You can also use specific font choices,
but you should test these on the actual devices being used.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 377
Chapter 13. Form Styling

Note: These two attributes, color and font-family, are the only style attributes sup-
ported in Collect.

378 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.3. Fonts and colors

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 379
Chapter 13. Form Styling

380 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.4. Emoji

XLSForm

type name label


note red Going <span style=”color:red”>red</span>
note green Going <span style=”color:#008000”>green</span>
note cursive <span style=”font-family:cursive”>Cursive text</span>
se- col- Formatting works on labels for Choices also.
lect_one ored_choices
yn
note combo # <span style=”font-family:cursive;color:purple”>Color and font
styling can be combined.</span>

Table 13.8: choices


list_name name label
yn yes <span style=”color:green”>Yes</span>
yn no <span style=”color:red”>No</span>

13.4 Emoji

Emoji can be used in form labels, hints, and answer choices.

Note: The exact visual representation of each emoji character is controlled by the device
operating system, and may vary from device to device. If possible, you should check how
your rendered forms look on the devices you are using for data collection.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 381
Chapter 13. Form Styling

XLSForm

Table 13.9: survey


type name label
select_one pain pain_level What is your current pain level?

Table 13.10: choices


list_name name label
pain 1 �
pain 2 �
pain 3 �
pain 4 �
pain 5 �
pain 6 �
pain 7 �

See also:
• Styling prompts in XLSForm

382 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
13.4. Emoji

• Sample XLSForm with Style

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 383
Chapter 13. Form Styling

384 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

FOURTEEN

FORM LANGUAGE

ODK Collect and XLSForm support multi-language forms.


To add additional languages to your XLSForm, add columns of user-facing content with
language-specific columns.
All columns representing user-facing text or media can be multi-lingual:
• label
• hint
• media::*
• constraint_message
• required_message
Each language column adds two colons and the language name, followed by the two letter
language code in parenthesis.
For example:
• label::English (en)
• hint::French (fr)
• media::image::Español (es)

Note: The text shown in Collect’s user interface (e.g., buttons, menus, dialogs) is controlled
by device language, not the form language. If you would like Collect’s user interface to
support your language, contribute translations at https://www.transifex.com/getodk.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 385
Chapter 14. Form Language

XLSForm — Single language

Table 14.1: survey


type name label hint
select_multiple colors color_prefs What colors do you like? Select three.

Table 14.2: choices


name label
header
list_name

colors red Red


colors blue Blue
colors yellow Yellow
colors green Green
colors orange Orange
colors purple Purple

XLSForm — Multiple languages

Table 14.3: survey


type name label::English label::Español hint::English hint::Español
(en) (es) (en) (es)
se- color_prefs
What colors do ¿Qué colores te Select Seleccione
lect_multiple you like? gustan? three. tres.
colors

Table 14.4: choices


list_name name label::English (en) label::Español (es)
colors red Red Rojo
colors blue Blue Azul
colors yellow Yellow Amarillo
colors green Green Verde
colors orange Orange Anaranjado
colors purple Purple Púrpura

386 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 387
Chapter 14. Form Language

Warning: There is no fallback language.


If you have specified languages for a column, the non-specific version of that column will
be treated as if it were a separate language. (The Change Language menu will list it as
Default.)
To avoid this, all columns that can be made multi-lingual need to be created as such for
a multi-language form. For example, even if using the same image for a question prompt
you will need a media::image::* column for each language. However, you may provide
the same media filename for each.
Blank cells in a language-specific column will be blank in the form when that language
is active, even if the ”default” column has a value.

XLSForm — Multiple languages with media example

Table 14.5: survey


type name label::English label::Español me- me-
(en) (es) dia::image::Español dia::image::English
(es) (en)
text cof- Do you want ¿Quieres mug_es.jpg mug_en.jpg
fee coffee? café?

14.1 Switching languages

Typically, if multiple languages are available on a form, the form will display in the language
set on the device.
To switch between available languages on a form, go to � → Change Language.

Note: Collect will remember the last language you switched to on a form, even if you
switch device language.
Changing the form’s language display will not change the device language. If you are in a
context that requires switching languages often, make sure you know where to do this in
your device’s Settings menu.

388 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

FIFTEEN

FORM OPERATORS AND FUNCTIONS

Expressions in calculations, constraints, and relevants can contain operators and functions.

• Operators
– Math operators
– Comparison operators
– Boolean operators
– Path operators
• Functions
– Control flow
– Accessing response values
– Strings
– Math
– Date and time
– Geography
– Utility

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 389
Chapter 15. Form Operators and Functions

15.1 Operators

15.1.1 Math operators

Explanation Example
+ addition ${salary_income} + ${self_employed_income}
- subtraction ${income} - ${expenses}
* multiplication ${bill} * 1.18
div division ${percent_int} div 100
mod modulo (division remainder) (${even_number} mod 2) = 0

Warning: Math operators only work with numbers.


• The addition operator cannot be used to concatenate strings. Use the concat()
function instead.
• Empty values (that is, variables referencing unanswered questions) are actually
empty strings, and will not be automatically converted to zero (0).

15.1.2 Comparison operators

Comparison operators are used to compare values. The result of a comparison is always
True or False.

Explanation Example Notes


= equal to ${enrolled} = ’yes’ Can compare numbers or strings.
!= not equal to ${enrolled} != ’yes’ Can compare numbers or strings.
> greater than ${age} > 17
>= greater than or equal to ${age} >= 18
< less than ${age} < 65
<= less than or equal to ${age} <= 64

Warning:
• The relational operators (>, >=, <, <=) only work with numbers.
• Empty response values are not automatically converted to zero (0).

390 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

15.1.3 Boolean operators

Boolean operators combine two True or False values into a single True or False value.

Explanation Example
and True if the expressions before and after are True ${age} > -1 and ${age} <
120
or True if either of the expressions before or after are ${age} < 19 or ${age} > 64
True

15.1.4 Path operators

Explanation Example Notes


. current question’s value . >= 18 Used in constraints.
.. current question’s parent posi- Used with position() to get the iteration
group tion(..) index.

Note: Formally, these are not operators but rather XPath references to the current node
(..) and the containing node (.). XPath paths can be used to reference nodes of a form.

15.2 Functions

• Control flow
• Accessing response values
– Select questions
– Repeat groups
• Strings
– Searching and matching strings
– Combining strings
– Converting to and from strings
• Math
– Number handling

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 391
Chapter 15. Form Operators and Functions

– Calculation
• Date and time
– Converting dates and time
– Formatting dates and times for display
• Geography
• Utility

See also:
Functions in the ODK XForm Specification

15.2.1 Control flow

if(expression, then, else)


Returns then if expression evaluates to True. Otherwise, returns else.
position(xpath)
Returns an integer equal to the 1-indexed position of the current node within the node
defined by xpath.
Most often this is used in the form position(..) to identify the current iteration index
within a repeat group.

392 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

XLSForm

type name label re- calculation


peat_count
note per- Please list the names of
son_list_note
the people in your house-
hold.
be- person Member of household
gin_repeat
text name Name
end_repeat
be- per- Details count(${person})
gin_repeat
son_details
calcu- cur- indexed-
late rent_name repeat(${name},
${person}, position(..))
date mem- Birthday of ${cur-
ber_bday rent_name}
end_repeat

once(expression)
Returns the value expression if the question’s value is empty. Otherwise, returns the
current value of the question.
This can be used to ensure that a random number is only generated once, or to store
the first value entered for a question in a way that is retrievable even if the response
is changed later.

Warning: This function is often misunderstood. Read when expressions are


evaluated to learn more.

15.2.2 Accessing response values

Note: The response from most question types can be accessed using variables. Functions
are needed for accessing responses to multi select questions and questions inside repeat groups.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 393
Chapter 15. Form Operators and Functions

Select questions

selected(space_delimited_array, string)
Returns True if string is a member of space_delimited_array, otherwise returns False.
Commonly used to determined if a specific choice was selected in a select question.
(This is possible because a reference to a select question returns a space-delimited
array of choice names.)
Video showing a series of select questions. The questions displayed change depending
on what choices are selected in the first questions.

394 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

XLSForm

Table 15.1: survey


type name label hint relevant con-
straint
se- what_issues
Have you expe- Select all that
lect_multiple rienced any of apply.
medi- the following?
cal_issues
se- what_cancer
What type of Select all that se-
lect_multiple cancer have you apply. lected(${what_issues},
can- experienced? ’cancer’)
cer_types
se- what_diabetes
What type of Select all that se-
lect_multiple diabetes do you apply. lected(${what_issues},
dia- have? ’diabetes’)
betes_types
be- blood_pressure
Blood pressure se-
gin_group reading lected(${what_issues},
’hypertension’)
integer sys- Systolic . > 40
tolic_bp and . <
400
integer dias- Diastolic . >=
tolic_bp 20 and .
<= 200
end_group
text other_health
List other is- se-
sues. lected(${what_issues},
’other’)
note af- This note is af-
ter_health_note
ter all health
questions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 395
Chapter 15. Form Operators and Functions

Table 15.2: choices


list_name name label
medical_issues cancer Cancer
medical_issues diabetes Diabetes
medical_issues hypertension Hypertension
medical_issues other Other
cancer_types lung Lung cancer
cancer_types skin Skin cancer
cancer_types prostate Prostate cancer
cancer_types breast Breast cancer
cancer_types other Other
diabetes_types type_1 Type 1 (Insulin dependent)
diabetes_types type_2 Type 2 (Insulin resistant)

selected-at(space_delimited_array, n)
Returns the string at the n�th position of the space_delimited_array. (The array is
zero-indexed.) Returns an empty string if the index does not exist.
This can be used to get the name of a selected choice from a multi-select question. (This
is possible because a reference to a select question returns a space-delimited array of
choice names.)

Note: If used to get a choice name from a select question, this function returns the
name, not the label, of the selected choice. To get the label in the current language,
use jr:choice-name().

396 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 397
Chapter 15. Form Operators and Functions

XLSForm

Table 15.3: survey


type name label hint calculation
se- color_prefs
What colors Select three.
lect_multiple do you like?
colors
calculate color_0 selected-
at(${color_prefs},
0)
calculate color_1 selected-
at(${color_prefs},
1)
calculate color_2 selected-
at(${color_prefs},
2)
note color_note
Selected col- ${color_0} <br>
ors: ${color_1} <br>
${color_2}

Table 15.4: choices


list_name name label
colors red Red
colors blue Blue
colors yellow Yellow
colors green Green
colors orange Orange
colors purple Purple

count-selected(multi_select_question)
Returns the number of choices selected in multi_select_question.

398 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

XLSForm

Table 15.5: survey


type name label hint constraint con-
straint_message
se- color_prefs
What colors do Select count- Select ex-
lect_multiple you like? three. selected(.)=3 actly three.
colors

Table 15.6: choices


list_name name label
colors red Red
colors blue Blue
colors yellow Yellow
colors green Green
colors orange Orange
colors purple Purple

jr:choice-name(choice_name, ’select_question’)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 399
Chapter 15. Form Operators and Functions

Returns the label value, in the active language, associated with the choice_name in
the list of choices for the select_question.

Note: You have to wrap the select_question reference in quotes.

'${question_name}'

400 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 401
Chapter 15. Form Operators and Functions

402 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

XLSForm

Table 15.7: survey


type name la- la- hint::English hint:Español calculation
bel::English
bel::Español
se- color_prefs
What ¿Qué Select three. Seleccione
lect_multiple colors col- tres.
colors do you ores te
like? gus-
tan?
calcu- color_0 jr:choice-
late name( selected-
at(${color_prefs},
0),
’${color_prefs}’)
calcu- color_1 jr:choice-
late name( selected-
at(${color_prefs},
1),
’${color_prefs}’)
calcu- color_2 jr:choice-
late name( selected-
at(${color_prefs},
2),
’${color_prefs}’)
note color_note
Se- Col- ${color_0} ${color_0}
lected ores <br> <br>
colors: selec- ${color_1} ${color_1}
ciona- <br> <br>
dos: ${color_2} ${color_2}

Table 15.8: choices


list_name name label::English label::Español
colors red Red Rojo
colors blue Blue Azul
colors yellow Yellow Amarillo
colors green Green Verde
colors orange Orange Anaranjado
colors purple Purple Púrpura

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 403
Chapter 15. Form Operators and Functions

Repeat groups

Helpful terms
nodeset A collection of XML nodes. In XLSForms, this is typically a collection of response
values.
Outside a repeat group, referring to a question by name will return a nodeset containing
all the responses to that question.
Nodesets can also be created by joining two or more nodes with pipes: /data/age |
/data/name.

indexed-repeat(name, group, i [, sub_grp, sub_i [, sub_sub_grp, sub_sub_i ]])


Returns the response value of question name from the repeat-group group, in iteration
i.
Nested repeat groups can be accessed using the sub and sub_sub parameters.
See also:
Referencing repeated questions from inside the repeat

XLSForm

type name label re- calculation


peat_count
note per- Please list the names of
son_list_note
the people in your house-
hold.
be- person Member of household
gin_repeat
text name Name
end_repeat
be- per- Details count(${person})
gin_repeat
son_details
calcu- cur- indexed-
late rent_name repeat(${name},
${person}, position(..))
date mem- Birthday of ${cur-
ber_bday rent_name}
end_repeat

404 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

count(nodeset)
Returns the number of items in nodeset. This can be used to count the number of
repetitions in a repeat group.

XLSForm

type name label re- calculation


peat_count
note per- Please list the names of
son_list_note
the people in your house-
hold.
be- person Member of household
gin_repeat
text name Name
end_repeat
be- per- Details count(${person})
gin_repeat
son_details
calcu- cur- indexed-
late rent_name repeat(${name},
${person}, position(..))
date mem- Birthday of ${cur-
ber_bday rent_name}
end_repeat

count-non-empty(nodeset)
Returns the number of non-empty members of nodeset.
sum(nodeset)
Returns the sum of the members of nodeset.
Can be used to tally responses to a repeated select question.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 405
Chapter 15. Form Operators and Functions

XLSForm

Table 15.9: survey


type name label calculation
begin_repeat guest_details Guest
details
text guest_name Guest name
select_one meal_preference
Meal pref-
meal_options erence
calculate chkn if(${meal_preference} =
’chicken’, 1, 0 )
calculate fsh if(${meal_preference} = ’fish’, 1,
0)
calculate veg if(${meal_preference} = ’vege-
tarian’, 1, 0 )
end_repeat
calculate chkn_count sum(${chkn})
calculate fsh_count sum(${fsh})
calculate veg_count sum(${veg})

Table 15.10: choices


list_name name label
meal_options chicken Chicken
meal_options fish Fish
meal_options vegetarian Vegetarian

max(nodeset)
Returns the largest member of nodeset.

XLSForm

Table 15.11: survey


type name label calculation
begin_repeat child_questions Questions about child
text child_name Child’s name
integer child_age Child’s age
end_repeat
calculate age_of_oldest_child max(${child_age})

406 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

min(nodeset)
Returns the smallest member of nodeset.

XLSForm

Table 15.12: survey


type name label calculation
be- child_questions Questions about
gin_repeat child
text child_name Child’s name
integer child_age Child’s age
end_repeat
calculate age_of_youngest_child min(${child_age})

Warning: The min() and max() functions only work sets of numbers. Empty values
(that is, variables referencing unanswered questions) are actually empty strings, and will
not be automatically converted to zero (0).

15.2.3 Strings

Searching and matching strings

regex(string, expression)
Returns True if string is an exact and complete match for expression.
See also:
Using regular expressions

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 407
Chapter 15. Form Operators and Functions

XLSForm

Table 15.13: survey


type name label constraint con-
straint_message
text mid- What is your middle ini- regex(., Just the first let-
dle_initial tial? ’p{L}’) ter.

contains(string, substring)
Returns True if the string contains the substring.
starts-with(string, substring)
Returns True if string begins with substring.
ends-with(string, substring)
Returns True if the string ends with substring.
substr(string, start [, end ])
Returns the substring of string beginning at the index start and extending to (but not
including) index end (or to the termination of string, if end is not provided). Members
of string are zero-indexed.

408 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

substring-before(string, target)
Returns the substring of string before the first occurrence of the target substring. If
the target is not found, or string begins with the target substring, then this will return
an empty string.
substring-after(string, target)
Returns the substring of string after the first occurrence of the target substring. If the
target is not found this will return an empty string.
translate(string, fromchars, tochars)
Returns a copy of string, where every occurrence of a character in fromchars is re-
placed by the corresponding character in tochars. If fromchars is longer than tochars
then every occurrence of a character in fromchars that does not have a corresponding
character in tochars will be removed.
string-length(string)
Returns the number of characters in string.
normalize-space(string)
Returns a string with normalized whitespace by stripping leading and trailing whites-
pace of string and replacing sequences of whitespace characters with a single space.

Combining strings

concat(arg [, arg [, arg [, arg [...]]]])


Concatenates one or more arguments into a single string. If any arg is a nodeset, the
values within the set are concatenated into a string.
join(separator, nodeset)
Joins the members of nodeset, using the string separator.

Converting to and from strings

boolean-from-string(string)
Returns True if string is ”true” or ”1”. Otherwise, False.
string(arg)
Converts arg to a string.

15.2.4 Math

Warning: Math functions (except number()) only work with number values.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 409
Chapter 15. Form Operators and Functions

You can use number() to convert a string of digits to a number, but it is usually better
to get a number value directly.
Empty values (that is, variables referencing unanswered questions) are actually empty
strings, and will not be automatically converted to zero (0).

Number handling

round(number, places)
Rounds a decimal number to some number of decimal places.
int(number)
Truncates the fractional portion of a decimal number to return an integer.
number(arg)
Converts arg to number value.
If arg is a string of digits, returns the number value.
If arg is True, returns 1. If arg is False, returns 0.
If arg cannot be converted, returns NaN (not a number).
digest(data, algorithm, encoding method (optional))
Computes and returns the hash value of the data string using the indicated hash
algorithm string, and encoding this hash value using the optional encoding string.
Options for the algorithm are MD5, SHA-1, SHA-256, SHA-384, SHA-512.
If the third parameter is not specified, the encoding is base64. Valid options for the
encoding are base64 and hex.
This function can be useful if, for example, someone wants to build a unique identifier
from sensitive data like a national ID number without compromising that data.
See also:
count(), max(), min(), number()

Calculation

pow(number, power)
Raises a number to a power.
log(number)
Returns the natural log of number.
log10(number)
Returns the base-10 log of number.

410 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

abs(number)
Returns the absolute value of number.
sin(number)
Returns the sine of number.
cos(number)
Returns the cosine of number.
tan(number)
Returns the tangent of number.
asin(number)
Returns the arc sine of number.
acos(number)
Returns the arc cosine of number.
atan(number)
Returns the arctan of number.
atan2(y, x)
Returns the multi-valued inverse tangent of y, x.
sqrt(number)
Returns the square root of number.
exp(x)
Returns e^x.
exp10(x)
Returns 10^x.
pi()
Returns an approximation of the mathematical constant π.

15.2.5 Date and time

today()
Returns the current date without a time component.
now()
Returns the current datetime in ISO 8601 format, including the timezone.

Warning: This function is often misused. Read when expressions are evaluated
to learn more.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 411
Chapter 15. Form Operators and Functions

Converting dates and time

decimal-date-time(dateTime)
Converts dateTime value to the number of days since January 1, 1970 (the Unix
Epoch).
This is the inverse of date().
date(days)
Converts an integer representing a number of days from January 1, 1970 (the Unix
Epoch) to a standard date value.
This is the inverse of decimal-date-time().
decimal-time(time)
Converts time to a number representing a fractional day. For example, noon is 0.5 and
6:00 PM is 0.75.

Formatting dates and times for display

format-date(date, format)
Returns date as a string formatted as defined by format.
The following identifiers are used in the format string:

%Y 4-digit year
%y 2-digit year
%m 0-padded month
%n numeric month
%b short text month (Jan, Feb, Mar…)
%d 0-padded day of month
%e day of month
%a short text day (Sun, Mon, Tue…).

Note: Month and day abbreviations are language and locale specific. If form locale
can be determined, that locale will be used. Otherwise, the device locale will be used.

format-date-time(dateTime, format)
Returns dateTime as a string formatted as defined by format.
The identifiers list in format-date() are available, plus the following:

412 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
15.2. Functions

%H 0-padded hour (24-hr time)


%h hour (24-hr time)
%M 0-padded minute
%S 0-padded second
%3 0-padded millisecond ticks.

15.2.6 Geography

area(nodeset | geoshape)
Returns the area, in square meters, of either a nodeset of geopoints or a geoshape
value.
It takes into account the circumference of the Earth around the Equator but does not
take altitude into account.
distance(nodeset | geoshape | geotrace)
Returns the distance, in meters, of either:
• a nodeset of geopoints
• the perimeter of a geoshape
• the length of a geotrace value
It takes into account the circumference of the Earth around the Equator and does not
take altitude into account.

15.2.7 Utility

random()
Returns a random number between 0.0 (inclusive) and 1.0 (exclusive).

Warning: This function is often misused. Read when expressions are evaluated
to learn more.

randomize(nodeset [, seed ])
Returns a shuffled nodeset.
A shuffle with a numeric seed is deterministic and reproducible.
The primary use for this function is to randomize the order of choices for a select
question. The documentation on select widgets describes how this is done in XLSForm.
randomize() can only be used in a context where a nodeset is accepted. Note that
questions of type calculate cannot reference a nodeset.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 413
Chapter 15. Form Operators and Functions

uuid([length ])
Without argument, returns a random RFC 4122 version 4 compliant UUID.
With an argument it returns a random GUID of specified length.
boolean(arg)
Returns True if arg is:
• a number other than zero
• a non-empty string
• a non-empty collection
• a comparison or expressions that evaluates to True.
Returns False if arg is:
• the number 0
• an empty string
• an empty collection
• a comparison or expression that evaluates to False.
not(arg)
Returns the opposite of boolean(arg).
coalesce(arg, arg)
Returns first non-empty value of the two arg�s. Returns an empty string if both are
empty or non-existent.
checklist(min, max, response[, response[, response[, ... ]]])
Returns True if the number of response�s that are exactly the string ”yes” is between
min and max, inclusive.
Set min or max to -1 to make the argument not applicable.
weighted-checklist(min, max, reponse, weight[, response, weight[, response,
weight[, response, weight[, ... ]]])
Returns True if the sum of the weight�s of each response that is exactly the string
”yes” is between min and max, inclusive.
Set min or max to -1 to make the argument not
true()
Evaluates to True.
false()
Evaluates to False.

414 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

SIXTEEN

LOGGING ENUMERATOR BEHAVIOR

Collect can log the behavior of enumerators as they navigate through a form. This log has
many uses including discovering:
• questions that take a long time to answer
• how enumerators typically navigate through a form
• enumerators who take a particularly long or short time to answer
• if enumerators were at the correct location when filling out a form
This information can inform form design and training.

If using Aggregate, Aggregate 1.5.0+ required


If a version of Aggregate lower than 1.5.0 is used, audit files will not be saved on the
server.

• Enabling audit logging


• Viewing audit logs
• Log structure
• Event types
• Timestamps
• Known limitations

16.1 Enabling audit logging

To enable logging for a form, add a row of type audit and name audit in an XLSForm:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 415
Chapter 16. Logging enumerator behavior

Table 16.1: survey


type name
audit audit

A form may contain at most one row of type audit.

16.1.1 Location tracking

You may add the location of events to the log. To do this, add the following parameters to
the XLSForm. All three parameters are required.
location-priority high-accuracy: The most accurate location provided by the device, re-
gardless of power use.
balanced: Block level accuracy (~100 meters). Uses less power than high-accuracy.
low-power: City level accuracy (~10 kilometers). Uses less power than balanced.
no-power: No locations will be returned unless another application on the device has
requested location updates. Uses no additional power.
location-min-interval The desired minimum time, in seconds, at which location updates
will be fetched by the device.
location-max-age The maximum time, in seconds, locations will be considered valid by
the device. Must be greater than or equal to location-min-interval.

Table 16.2: survey


type name parameters
au- au- location-priority=balanced location-min-interval=60 location-max-
dit dit age=120

When location tracking is enabled, ODK Collect requests location updates from Android
periodically, with an interval determined by location-min-interval. The requests are sent
with location-priority to ensure Android does not use more power than is desired.
When Collect receives the location updates, it stores the locations in a timestamped cache.
At the time of an event, Collect checks the cache for locations stored over the last location-
max-age and returns the most accurate location in the cache.
For the most accurate locations, set location-priority to high-accuracy. For the most recent
locations, use low numbers for location-min-interval and location-max-age.

416 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
16.1. Enabling audit logging

Warning: Location tracking can be an invasion of privacy. Users of ODK Collect will
be informed that their location is being tracked when they open a form with this feature
enabled.
Users can control their privacy by disabling location providers in Android, refusing to
grant Collect location permissions, or by disabling location tracking of specific forms in
Collect.
Disabling location tracking will not prevent users from filling out forms, but these changes
are logged as events in the log.

16.1.2 Change tracking

You can enable change tracking so that old answers and new answers will be added to
the question events. To do this, add the following parameter to the XLSForm: track-
changes=true.

Table 16.3: survey


type name parameters
audit audit track-changes=true

16.1.3 Tracking reason for edit

New in version 1.25: ODK Collect v1.25.0


You can add to track-changes-reasons=on-form-edit to prompt enumerators to enter a reason
before they save changes to a form:

Table 16.4: survey


type name parameters
audit audit track-changes-reasons=on-form-edit

This will prevent filled out forms being edited without a reason being given. If a reason is
given the form will be saved normally and the audit log will include a change reason event
with the reason recorded in the change-reason column.

16.1.4 Enumerator identification

ODK Collect v1.25.0


If your form needs a record of the identity of the enumerator you can use identify-user=true.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 417
Chapter 16. Logging enumerator behavior

Table 16.5: survey


type name parameters
audit audit identify-user=true

This will cause Collect to prompt the enumerator for their identity before filling out or editing
a form instance. In the audit log, a user column will be included that will be populated for
each event. The enumerator will not be able to fill in or edit the form without entering a
non-blank identity.

Tip: identify-user is useful for data collection workflows where devices might be passed
between multiple enumerators for data verification or completion.
In cases where a device will only ever used by a single enumerator, it might make more sense
to use username metadata. This will write the username to each submission instead of to
the audit log.

16.2 Viewing audit logs

Central will export a CSV with audits from all submissions if an export is requested for a
form with an audit.
If using Aggregate, audit logs can be reviewed and downloaded for further analysis using
Briefcase.
In Aggregate 1.5.0+, audit logs can be viewed by clicking on the media icon in the meta
audit column on the Submissions page:

This displays a popup with the audit contents:

418 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
16.3. Log structure

Tip: Aggregate currently only displays event, node, start, and end in the audit popup.
To view locations, changed answers, or to perform more sophisticated analysis, logs can be
downloaded along with their submissions using Briefcase.

16.3 Log structure

If a form includes an audit, Collect will create an audit.csv file as the form is filled out.
The audit.csv file has the following structure:

Table 16.6: audit.csv


event node start end
question /data/name 1523403169208 1523403170733

Values in the event column represent a particular user action such as opening a form, saving a
form, or displaying a question. Possible event types are described in the Event types section.
Values in the node column represent the node in the form that the event refers to, if appli-
cable.
Values in the start and end columns are timestamps represented as the number of milliseconds
since midnight, January 1, 1970 UTC. This is known as epoch time and provides a standard
way of representing date/time even across timezones. The Timestamps section contains more
information about timestamps.
If both location tracking and change tracking are enabled in the log, the CSV will look like
this:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 419
Chapter 16. Logging enumerator behavior

Table 16.7: audit.csv


event node start end lati- lon- accuracy old- new-
tude gi- value value
tude
form start 1550615022663
location track- 1550615022671
ing enabled
question /data/name
1550615022682
1550615097082
37.4229983
- 14.086999893188477John
122.084
location 1550615068610
permissions
granted
location 1550615068665
providers
enabled
location track- 1550615095914 37.4229983
- 14.086999893188477
ing disabled 122.084
question /data/age
1550615097082
1550615097655
37.4229983
- 14.08699989318847720
122.084
question /data/name
1550615097656
1550615102351
37.4229983
- 14.086999893188477
John John
122.084 Smith
location track- 1550615099271 37.4229983
- 14.086999893188477
ing enabled 122.084
question /data/age
1550615102351
1550615107630
37.4229983
- 14.086999893188477
122.084
end screen 1550615107631
1550615109199
37.4229983
- 14.086999893188477
122.084
form save 1550615109199 37.4229983
- 14.086999893188477
122.084
form exit 1550615109199 37.4229983
- 14.086999893188477
122.084
form finalize 1550615109199 37.4229983
- 14.086999893188477
122.084

Values in the latitude and longitude columns represent the latitude and longitude in decimal
degrees. Values in the accuracy column represents accuracy in seconds.

Note: Locations will often be repeated in the log. This is because locations are not
captured at the time of the event, but rather retrieved from a cache of the most accurate
points captured over the last location-max-age.

420 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
16.4. Event types

Note: Answers will be recorded only if they differ (if the new answer is different than the old
one), otherwise, cells should be empty. Answers which contain commas will be surrounded
by double quotes.

16.4 Event types

The event column of the audit log can have the following values:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 421
Chapter 16. Logging enumerator behavior

Event Description Node?Timestamps?Coordi- An-


nates? swers?
form start Start filling in the form No start If enabled No
only and avail-
able
question View a question Yes Yes If enabled If
and avail- en-
able abled
group questions View multiple questions on Yes Yes If enabled No
one screen (field-list) and avail-
able
jump View the jump screen No start If enabled No
only and avail-
able
add repeat Add a repeat Yes Yes If enabled No
and avail-
able
delete repeat Delete a repeat Yes Yes If enabled No
and avail-
able
end screen View the end screen No Yes If enabled No
and avail-
able
form save Save the form No start If enabled No
only and avail-
able
form exit Exit the form No start If enabled No
only and avail-
able
form resume Resume the form No start If enabled No
only and avail-
able
form finalize Finalize the form No start If enabled No
only and avail-
able
save error Error trying to save No start If enabled No
only and avail-
able
finalize error Error trying to finalize the No start If enabled No
form (probably encryption only and avail-
related) able
constraint error Constraint or required error No start If enabled No
on finalize only and avail-
able
location tracking Toggle location tracking in No Yes If enabled No
422
enabled/disabled Collect
Our documentation and avail-
is updated frequently. Get the latest version at https://docs.getodk.org.
able
location providers Toggle location providers in No Yes If enabled No
16.5. Timestamps

16.5 Timestamps

If we relied entirely on the time reported by the device for timestamps, users or the network
could change the device time and manipulate the correctness of the audit log. For this reason,
we only use device time for the form start timestamp. All subsequent event timestamps are
the result of elapsed time, which users cannot change, added to the form start timestamp.
This means that while the timestamps themselves may potentially be inaccurate, the time
elapsed within and between the timestamps are always accurate within one form editing
session.
Using epoch time makes it easy to compute elapsed time by subtracting start from end. For
example, given the following log:

Table 16.8: audit.csv


event node start end
form start 1488761807863
question /data/name 1488761807868 1488761809157

The enumerator spent 1488761809157 - 1488761807868 = 1289 milliseconds on the screen


showing the /data/name question. This corresponds to 1289 / 1000 = 1.289 seconds.
To convert from epoch time to time in UTC in most common spreadsheet programs, divide
the epoch time by 86400000 ms per day and add 25569 days between January 1, 1900 (what
spreadsheet programs use as ”day zero”) and January 1, 1970. For example, to convert the
timestamp 1488761807868:

(1488761807868 / 86400000) + 25569 = 42800.03944

When the cell is set to type date time in common spreadsheet programs, it will show 3/
6/2017 0:56:48 UTC. A common workflow if device time is needed in a human-readable
format will be to add a column for the calculation above and change that column’s type to
date time.

16.6 Known limitations

• If the device is turned off while a form is being filled, Collect will not record a log entry
for the screen that was shown at the time of device shutdown. Events before and after
the shutdown will be logged.
• Editing a saved form that was saved using different audit log options can result in
a corrupt audit. It might take place when a user saves a form then updates a form
definition (changing audit log options) and tries to edit the saved form.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 423
Chapter 16. Logging enumerator behavior

424 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

SEVENTEEN

LAUNCHING EXTERNAL APPS

See also:
Launching ODK Collect from External Apps

17.1 Launching external apps to populate single fields

ODK Collect can launch external applications using the ex:intentAction(intentExtras)


appearance on string, integer or decimal fields. The application launched could be one that
the enumerator uses and quits without Collect needing any data from it. For example, a
form could configure the Maps.me application to provide directions to a destination and not
need any information back from the app. An external application could also be used to
populate the string, integer or decimal field that launched it. In order to populate a field,
the app that is launched must be designed to returned a value as described in the external
app design section below.
This feature configures an Android intent. Intents are messaging objects used to request an
action from another app component. Learn more in the Android docs.
Collect builds the action using the text immediately after ex: and before an open-
ing parenthesis (if it exists). For example, in the string ex:org.opendatakit.
counter(intentExtras), the action name is org.opendatakit.counter. An action name
must include a namespace, such as org.opendatakit or com.google. For example, ex:org.
opendatakit.counter is valid but ex:counter is not.
The parameters defined in the optional parentheses represent extended data (”extras”) to be
added to the intent. Extras are specified by a comma-delimited list of name=value pairs. The
text to the left of the equals sign represents the extra name and may require a namespace.
The text to the right of the equals sign represents the extra value.
The values of extras can be:
• XPath expressions referring to other fields and including function calls
• String literals defined in single quotes

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 425
Chapter 17. Launching External Apps

• Raw integers or decimals


An extra named value that holds the current value for the current field is always passed
with the intent. Since v1.4.3, additional parameters with user-defined names can be specified.
There are two reserved names: value and uri_data.
Since Collect v1.16.0, the data that the intent operates on can be set by using the reserved
uri_data parameter. This is particularly useful for implicit intents such as android.intent.
action.SENDTO.

17.1.1 XLSForm

Table 17.1: survey


type name label appearance
in- counter
Click launch to ex:org.opendatakit.counter(form_id=’counter-form’,
te- start the counter form_name=’Counter Form’, question_id=’1’, ques-
ger app tion_name=’Counter’)

In the examples above, the extras specified have names form_id, form_name, question_id,
and question_name.

17.2 Designing an external app to return a single value to


Collect

When an activity that is launched returns to Collect, Collect will look for an intent extra
named value and use its value to populate the field that triggered the application launch.
See a counter app to see an example of how this is done.

17.3 Launching external apps to populate multiple fields

Since v1.4.3, a field-list group can have an intent attribute that allows an external
application to populate it. Notice that the ex: prefix used when populating a single field is
not included to populate multiple fields.

426 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
17.4. Specifying a URI as intent data

17.3.1 XLSForm

Table 17.2: survey


type name label ap- body::intent
pear-
ance
be- my- Fields to field- org.mycompany.myapp(my_text=’Some text’,
gin_groupgroup populate list uuid=/myform/meta/instanceID)
text some- Some text
text
integer somein- Some inte-
teger ger
end_group

<group ref="/myform/mygroup" appearance="field-list"


intent="org.mycompany.myapp(my_text='Some text',
uuid=/myform/meta/instanceID)">
<label>Fields to populate</label>
<input ref="/myform/mygroup/sometext">
<label>Some text</label>
</input>
<input ref="/myform/mygroup/someinteger">
<label>Some integer</label>
</input>
</group>

The intent attribute is only used when the group has an appearance of field-list. The
format and the functionality of the intent value is the same as above. If the bundle of
values returned by the external application contains values with keys that match the type
and the name of the sub-fields, then the values from the bundle overwrite the current values
of those sub-fields.
The external app is launched with the parameters that are defined in the intent string plus
the values of all the sub-fields that are either text, decimal, or integer. Any other sub-field
is invisible to the external app.

17.4 Specifying a URI as intent data

Since Collect v1.16.0, the value for the reserved parameter name uri_data is converted to
a URI and used as the data for the intent. The intent data determines which application to
launch when using implicit intents such as SENDTO. For example:
ex:android.intent.action.SENDTO(uri_data='smsto:5555555', sms_body=${message})

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 427
Chapter 17. Launching External Apps

Launches a new message in an SMS app with the destination number set to 5555555
and the message body set to the contents of the message field.
ex:android.intent.action.SENDTO(uri_data='mailto:example@example.com?subject=${subject}
Launches a new message in an email app with destination address set to
example@example.com, the subject set to the contents of the subject field and
the body set to the contents of the message field.
ex:android.intent.action.DIAL(uri_data='tel:5555555') Launches a phone dialer
with the number 5555555 as the number to dial.
Notice that the URI must include a scheme, such as mailto: or https://.

428 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

EIGHTEEN

FORM BUILDING TOOLS

18.1 ODK Build

ODK Build is a form designer with a drag-and-drop user interface. Build is an HTML5 web
application and works best for designing simple forms.

Tip: For a more powerful form designer from ODK, try XLSForm.

18.1.1 Using ODK Build

Go to http://build.getodk.org and sign in.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 429
Chapter 18. Form Building Tools

Note: There is a downloadable version of ODK Build available.

Tip: Clicking on About ODK Build… option in the Help menu provides basic information
about ODK Build.

430 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.1. ODK Build

Creating and Saving forms

Options to create, open and save forms are available in the File menu.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 431
Chapter 18. Form Building Tools

• Click on New Form to start creating a new form.

Tip: When you start building a form on ODK Build, it is named as Untitled Form. To
rename it click on rename next to the form name and give a name to your form.

• Click on Open Form… to open a saved form and edit it. Select the form and click on
Open option in the open form window. You can also delete a saved form by clicking
on X beside the form name.

• To save a form click on Save. If you want to save an edited version of a previously
saved form as a new form, click on Save Form as… and provide a name to the form.
• To save your form on your local machine, click on Save Form to File…. You can open
a form saved into your local machine by clicking on Load Form from File….

432 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.1. ODK Build

Note: Forms which are saved to your local machine have extension .odkbuild and only
these forms can be loaded into ODK Build.

Form building

• Add a new prompt, by dragging the elements from the bottom of the screen onto the
blank canvas.
• You can remove a prompt by clicking on X sign on the prompt.

• For each prompt, modify its properties on the right portion of the screen.

• Prompts can also be rearranged through drag and drop.


• You can collapse the question prompts by checking the Collapse Questions option in
the View menu.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 433
Chapter 18. Form Building Tools

• Information about prompts is displayed in the properties section.

• Unchecking the Show Information option in the Help menu will hide the information
which is displayed in properties section.

434 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.1. ODK Build

Upload forms to Aggregate

You can upload a form to Aggregate server by clicking on Upload Form to Aggregate… in
the File menu. In the window which opens up, enter the url for your Aggregate server.
In the username and password box, you need to enter your Aggregate account credentials
with Form Manager or greater capabilities. The account type in Aggregate has to be ODK,
not Google. You may leave these blank if your Aggregate instance allows anonymous form
uploading.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 435
Chapter 18. Form Building Tools

Export forms

• To view XML for your form, click on Export to XML… in the File menu. You can
download the .xml file for your form by clicking on Download option in the output
XML window.

• You can download .xlsx file for your form by clicking on Export to XLSForm in the
File menu.

Changing form properties

You can change the form properties by clicking Form Properties… in the Edit menu.

436 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.1. ODK Build

A form properties window will appear, where you can enter the instance name, public key
and submission url for your form.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 437
Chapter 18. Form Building Tools

Instance name specifies names you want to give to submitted data. You can see more info
on public key here. Submission url directs your submissions somewhere other than the
Aggregate that supplied the form. This is the ODK Aggregate website url with Aggregate.
html replaced by submission.

Tip: You can give an instance name which uses calculated expressions to name submissions
based on submission data. Note that whatever you put in the instance name box should
evaluate to a string.
For example, you might use a concatenation of a unique student ID (sid) with the student
name (s_name) as the name of the filled-in form. So you can provide a instance name as :
concat(${sid},’ - ’, ${s_name}).
This is implemented in XML as an instanceName field within the meta block. If this value
is present and not an empty string (””), it will be used as the name of the filled-in form.
Otherwise, the current default naming, based upon the date the form was first saved, will
be used.

<instance>
<data id="build_example1_1508999324">
<meta>
<instanceID/>
<instanceName/>
</meta>
<s_name/>
<sid/>
</data>
</instance>

Fig. 18.1: Instance name as sid-s_name: 12345-Ankita

Add, remove and display new languages

You can add a new language for your form by clicking on Manage Translations… in the Edit
menu.

438 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.1. ODK Build

When you add a new language, the language box will be displayed in the properties section
of the form.

You can also remove any translation by clicking on remove option in the Translation box.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 439
Chapter 18. Form Building Tools

You can change the display language for your form by checking the language you want to
use as display language in the View menu.

18.2 ODK Validate

ODK Validate is a tool that ensures an XForms XML file conforms to the XForms specifi-
cation.
Validate should be used to check hand-edited XForms. It is not needed when creating forms
with XLSForm or ODK Build, unless you edit those forms manually after creating them.

18.2.1 Setting up Validate

440 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
18.2. ODK Validate

Note: The Validate file available for download is an executable Java application. Once
downloaded, it can be run directly and does not need to be installed.

Before you begin…


Make sure Java 8 is installed on your system.

1. Download Validate.
2. If you wish, move Validate to your Applications directory or another suitable loca-
tion.

18.2.2 Using Validate

1. Open Validate.
2. Find your XForms *.xml file using Choose file, and Open it.
3. Review and fix any warning messages.

4. If needed, Validate Again.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 441
Chapter 18. Form Building Tools

Command line

Validating a single form:

$ java -jar {path/to/validate-jar-file} {path/to/xform.xml}

Validating multiple forms:

$ java -jar {path/to/validate-jar-file} [--fail-fast] {path/to/xform1.xml} {path/


,→to/xform2.xml} {path/to/xform3.xml}

The optional –fail-fast flag tells Validate to exit on the first error rather than validating all
forms and reporting an error at the end.

Warning: This tool validates XML files against the XForms specification. It does
not check every detail needed to ensure smooth operation in the ODK ecosystem. For
example, Aggregate requires that forms have a unique form ID, which this tool does not
check.

442 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

NINETEEN

TIPS AND BEST PRACTICES

19.1 Repeat Recipes and Tips

See also:
Repeating questions describes repeat basics.

• Referencing repeated questions from inside the repeat


• Referencing repeated questions from outside the repeat
• Counting repeats and answers
– Counting the total number of repeat instances
– Counting the number of times a particular answer was given
• Using additional repeats to follow up on repeated questions
• Setting a max limit on repetitions
– Using a constraint to limit repetitions
– Using relevants to limit repetitions

19.1.1 Referencing repeated questions from inside the repeat

Within a repeat, you can reference other questions in that same repeat instance in the
usual manner.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 443
Chapter 19. Tips and Best Practices

XLSForm

Table 19.1: survey


type name label
note child_questions_note
Please provide the following details about each child in
your household.
be- child_details Children in household
gin_repeat
text child_first_name Name
text child_age Age of ${child_first_name}
end_repeat

To reference a question from a different repeat instance, or from outside the repeat, use
indexed-repeat() and position().

19.1.2 Referencing repeated questions from outside the repeat

A question in a repeat can be referenced from outside the repeat with indexed-
repeat(${question-name}, ${repeat-name}, index).

19.1.3 Counting repeats and answers

Counting the total number of repeat instances

Use count(${name-of-repeat}) to get the number of repeat instances.

Counting the number of times a particular answer was given

To count the number of times a specific response is given, add a calculate field inside the
repeat which evaluates to 1 or 0 depending on the answer. Then, outside the repeat, calculate
the sum() of the calculate field.

444 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.1. Repeat Recipes and Tips

XLSForm

Table 19.2: survey


type name label calculation
begin_repeat guest_details Guest de-
tails
text guest_name Guest name
select_one meal_preferenceMeal prefer-
meal_options ence
calculate chkn if(${meal_preference} = ’chicken’,
1, 0 )
calculate fsh if(${meal_preference} = ’fish’, 1, 0
)
calculate veg if(${meal_preference} = ’vegetar-
ian’, 1, 0 )
end_repeat
calculate chkn_count sum(${chkn})
calculate fsh_count sum(${fsh})
calculate veg_count sum(${veg})

Table 19.3: choices


list_name name label
meal_options chicken Chicken
meal_options fish Fish
meal_options vegetarian Vegetarian

19.1.4 Using additional repeats to follow up on repeated questions

Sometimes it is convenient to gather an initial set of responses, and then ask more detailed
question after you have collected the whole set.
For example:
• collecting the names of all the people in a household, and then asking questions about
each person
• collecting the names of each type of crop being grown, and then asking questions about
each crop
This can be done by using count() and position(..). count() is used to guarantee that the
second repeat has the same number of instances as the original repeat. position(..) provides
the index of the repeat instance it was called from. This is used to refer to questions from
the first repeat in the follow-up repeat.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 445
Chapter 19. Tips and Best Practices

XLSForm

type name label re- calculation


peat_count
note per- Please list the names of the
son_list_note
people in your household.
be- person Member of household
gin_repeat
text name Name
end_repeat
be- per- Details count(${person})
gin_repeat
son_details
calcu- cur- indexed-repeat(${name},
late rent_name ${person}, position(..))
date mem- Birthday of ${cur-
ber_bday rent_name}
end_repeat

19.1.5 Setting a max limit on repetitions

If you want the user to decide how many times to repeat, but you also want to limit the
maximum number of repetitions, you have a few options.

Using a constraint to limit repetitions

If the user knows how many repetitions they will complete, you can ask them this in a
question before the repeat group and set a constraint on that question.

446 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.1. Repeat Recipes and Tips

XLSForm

Table 19.4: survey


type name label con- repeat_count
straint
integer num- How many guests are in your . <= 8
ber_in_party party?
note party_names_note
Please provide details for each
guest.
be- guest_details Guest details ${num-
gin_repeat ber_in_party}
text guest_name Guest’s name
text guest_dietary Does this guest have any dietary
restrictions?
end_repeat

Note: If the count is decreased by a user, no groups will be deleted. This avoids accidental
data loss: a user who accidentally sets the count too low can set it to a higher number and
still have the repetitions that were previously created.

A recommended way to handle this case is using relevance to hide any extra values:

Table 19.5: survey


type name label con- re- relevant
straint peat_count
integer num- How many guests are in .
ber_in_partyyour party? <=
8
note party_names_note
Please provide details
for each guest.
be- guest_detailsGuest details ${num-
gin_repeat ber_in_party}
be- guest_details_gr position(..)
gin_group <= ${num-
ber_in_party}
text guest_nameGuest’s name
text guest_dietary
Does this guest have
any dietary restric-
tions?
end_group
end_repeat

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 447
Chapter 19. Tips and Best Practices

Using relevants to limit repetitions

If asking the user ahead of time doesn’t make sense, another strategy is to manually repeat
the question in the form and use the relevant column to skip repetitions if the previous
question is left blank. This sets a maximum number of responses: the number of times you
included the question in the form.
To check if the previous question has a response, reference the question in the relevant
column.

XLSForm

Table 19.6: survey


type name label relevant
note images_note Take up to five pictures.
image image_1 Image 1
image image_2 Image 2 ${image_1}
image image_3 Image 3 ${image_2}
image image_4 Image 4 ${image_3}
image image_5 Image 5 ${image_4}

This pattern can be combined with required responses to enforce a minimum number of
responses.

XLSForm

Table 19.7: survey


type name label required relevant
note images_note Take 3-5 pictures.
image image_1 Image 1 yes
image image_2 Image 2 yes
image image_3 Image 3 yes
image image_4 Image 4 ${image_3}
image image_5 Image 5 ${image_4}

448 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.2. Using regular expressions

19.2 Using regular expressions

19.2.1 Regular Expressions

A regular expression is a special text string for describing a search pattern. Regular expres-
sions find an important use in specifying constraints in your forms. You might want to set
constraints on the length, character set allowed and various other fields in the data input by
the user. All this can be achieved by using regular expression constraints in your form.
Some basic operations on regular expressions are:
1. Boolean or: A vertical bar separates alternatives. For example, gray|grey can match
gray or grey.
2. Grouping Parentheses: They are used to define the scope and precedence of the
operators. For example, gray|grey and gr(a|e)y are equivalent patterns which both
describe the set of gray or grey.
3. Quantification: A quantifier after a token (such as a character) or group specifies
how often that preceding element is allowed to occur.
• Square brackets indicate the occurrence of elements within. For example, [abc]
matches either a, b or c character, [a-g] matches any character from a to g,
[^abc] matches any character except a,b or c.
• The question mark indicates zero or one occurrence of the preceding element. For
example, colou?r matches both color and colour.
• The asterisk indicates zero or more occurrences of the preceding element. For
example, ab*c matches ac, abc, abbc, abbbc, and so on.
• The plus sign indicates one or more occurrences of the preceding element. For
example, ab+c matches abc, abbc, abbbc, and so on, but not ac.
• {n}: The preceding item is matched exactly n times.
• {min,}: The preceding item is matched min or more times.
• {min,max}: The preceding item is matched at least min times, but not more than
max times.
For a clear understanding of regular expressions, try these regex online checker tools:
• https://regex101.com/
• https://www.regextester.com/
• https://regexr.com/
• http://www.regexe.com/.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 449
Chapter 19. Tips and Best Practices

19.2.2 Tips on using regular expressions

• Regular expressions only apply to strings. The function used is of the form:
regex(string value, string expression) where it returns the result of regex test
on provided value. If the result is true, the input value is valid and satisfies the con-
straint. If the result is false, input value is not valid and user may need to re-enter the
input. The regex function will be placed in the constraints column in your XLSForm.
• Be careful while setting limits on length of a constraint. For example, if you want
to restrict a text input to a maximum of six alphabetic characters, you can do so as
follows:
In XLSForm:

Table 19.8: Survey


type name label constraint constraint_message
text ex Enter ex- regex(.,’^[a-zA- Input can have a maximum of 6 al-
ample Z]{0,6}$’) phabetic characters.

In XForm XML:

<bind constraint="Regex(.,'^[a-zA-Z]{0,6}$')" jr:constraintMsg="Input␣


,→can have a maximum of 6 alphabetic characters." nodeset="/regex_ex/ex

,→" type="string"/>

<input ref="/regex_ex/ex">
<label>Enter example</label>
</input>

Instead if you used a constraint of the form regex(.,'^[a-zA-Z]{6}$'), it


would require an input of exactly six alphabetic characters.

Note:
• . denotes the input string.
• ^ and $ denote start and end of string respectively.

• If you want to use a regular expression constraint on a number, make sure that the type
of your question is text and appearance is numbers and then apply the constraint.
The following example will validate a 10-digit North American telephone num-
ber. Separators are not required, but can include spaces, hyphens, or periods.
Parentheses around the area code are also optional.
In XLSForm:

450 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.2. Using regular expressions

Table 19.9: Survey


type name label constraint constraint_message ap-
pear-
ance
text tel_noEnter regex(.,’^(([0-9]{1})*[- Telephone numbers num-
your Tele- .(]*([0-9]{3})[- should have 10 dig- bers
phone .)]*[0-9]{3}[- .]*[0- its with optional
number 9]{4})+$’) separators.

In XForm XML:

<bind constraint="Regex(.,'^(([0-9]{1})*[- .(]*([0-9]{3})[- .)]*[0-9]


,→{3}[- .]*[0-9]{4})+$')" jr:constraintMsg="Telephone numbers should␣

,→have 10 digits with optional separators." nodeset="/regex_ex/tel_no"␣

,→type="string"/>

<input appearance="numbers" ref="/regex_ex/tel_no">


<label>Enter your Telephone number"</label>
</input>

An other alternative to this would be to use a regular expression of the form:


regex(string(.),'...'). But this should be avoided since the value of string(.)
would be after whatever you entered was converted to an integer. So if you
entered 0004, string(.) would be 4.
• Integers are limited by binary representation to 9 decimal digits. If you want something
longer (like 10 numbers) then make sure to use a text type with appearance as numbers
and add a constraint restricting the input string to be a number. Constraint is required
since appearance setting changes the keyboard style of the pop-up keyboard to the
number keyboard when you attempt to enter data into the field but does not prevent
non-numbers from being entered. This relies upon the device’s keyboard supporting
(See this).
For example, a constraint of the form regex(.,'^[0-9]{11}$') will restrict the
input string to be a number of exactly 11 digits.
• Avoid using complex regex patterns as that may cause stack overflow crashes. Also,
avoid placing constraints on names since your regex will certainly not capture all the
punctuation or random characters that names can contain and they are hard error-
prone and hard to maintain.
See also:
You can refer this list for various common regex patterns.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 451
Chapter 19. Tips and Best Practices

19.3 Updating forms in Aggregate

Note: This page is only about ODK Aggregate. ODK Central allows any kind of form
update that doesn’t change the type of a field. See Updating Forms to a New Version.

19.3.1 Making changes to existing form

Certain changes which don’t involve adding or removing a question can be made without
needing to replace the existing forms. The kind of changes are:
• Changing the text or translation of a label
• Changing validations, calculations, relevants
• Changing options for a select_one or select_multiple
• Changing the order of questions
• Adding translations
• Updating media including CSVs for your form
For such changes you can update the version and re-upload the form.

Note:
• If you add new media files or update existing media files for your form without any
change in the form definition file or .xml file, you don’t need to change the version.
• If you have used external select and add, update or delete the choices in external .csv
file without any change in the form definition file or .xml file, you don’t need to change
the version. For more details on using external choices in your form, see this

Tip: Form version in XLSForm is a string of up to 10 numbers that describes this revision.
Revised form definitions must have numerically greater versions than previous ones. A
common convention is to use strings of the form yyyymmddrr. For example, 2017120701
is the 1st revision from Dec 7th, 2017.

For example:

452 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.3. Updating forms in Aggregate

Table 19.10: Survey


type name label con- con- rele- read_only
de- re- calcu-
straintstraint_message vant fault quiredlation
text name Enter your yes
name
inte- sid Enter your yes
ger student id
inte- age Enter your age .<=18You should be be- yes
ger low 18 years to be
eligible for the sur-
vey.
se- courseIn which de- yes
lect_one partment have
dept you chosen
courses?
inte- course_cnt
Enter number 1<=.<=6
You should choose ${course}!=’none’ yes
ger of courses you at least 1 course
have chosen and at most 6
courses.
inte- marksEnter total ${course}!=’none’ yes
ger marks ob-
tained in all
courses
cal- to- ${course_cnt}!=” ${course_cnt}*100
cu- tal
late

Table 19.11: Choices


list name name label
dept Physics PHY
dept Math MAT
dept Chemistry CHEM
dept none none

Table 19.12: Settings


form_title form_id default_language version
Example_form example_id English 2017120700

If you want to make the following changes to the above form:


• Add a Spanish translation

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 453
Chapter 19. Tips and Best Practices

• Change the relative order of first and second question


• Change age constraint from 18 to 20
• Change the sid field to not required
• Change label for third question from In which department have you chosen
courses? to Name of Department.
• Change the calculation from ${course_cnt}*100 to ${course_cnt}*50
• Change the relevant for calculate to ${course}!=’none’ and ${course_cnt}!=”
• Change the list name in choices from dept to dept_name
• Add a new choice in department list as Computer
• Change Math to Mathematics and MAT to MATH in choices
These changes can be made as:

454 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.3. Updating forms in Aggregate

Table 19.13: Survey


type name la- la- con- con- relevant read_only
de- re- cal-
bel::Englishbel::Español straintstraint_message fault quiredcu-
(en) (es) la-
tion
in- sid Enter Ingrese su no
te- your identifi-
ger student cación de
id estudiante
text name Enter Introduzca yes
your su nombre
name
in- age Enter Introduzca .<=20You should yes
te- your su edad be below 20
ger age years to be
eligible for
the survey.
se- courseName Nombre del yes
lect_one of departa-
dept_name Depart- mento
ment
in- course_cnt
Enter Ingresa el 1<=.<=6
You should ${course}!=’none’ yes
te- num- número de choose at
ger ber of cursos que least 1
courses has elegido course and
you at most 6
have courses.
chosen
in- marksEnter Ingrese ${course}!=’none’ yes
te- total las califi-
ger marks caciones
ob- totales
tained obtenidas
in all en todos los
courses cursos
cal- to- ${course}!=’none’ ${course_cnt}*50
cu- tal and
late ${course_cnt}!=”

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 455
Chapter 19. Tips and Best Practices

Table 19.14: Choices


list name name label
dept_name Physics PHY
dept_name Mathematics MATH
dept_name Chemistry CHEM
dept_name Computer COMP
dept_name none none

Table 19.15: Settings


form_title form_id default_language version
Example_form example_id English 2017120701

Note: You need to use the same filename when generating newer versions of your form
since the XLSForm converter uses that filename in creating the form structure which is used
by the server to help determine uniqueness.
If you use the same filename, you can upload the form and ODK Aggregate will automatically
replace the old version and keep the existing form data. If you use different filenames, you
would need to delete the old version of the form (and the existing form data) in order to
upload the newer version.
In the examples below, we use different filenames for version upgrade since unique filenames
are required for uploading files to the documentation website.
Due to different XLSForm filenames in these examples, the generated XForms will have
different instance definition as follows:
For example_form_v1.0.xlsx:

<instance>
<example_form_v1.0 id="example_id" version="2017120700">

For example_form_v1.1.xlsx:

<instance>
<example_form_v1.1 id="example_id" version="2017120701">

These are the .xml files for the above forms:


1. example_form_v1.0
2. example_form_v1.1
These are the .xlsx files for the above forms:

456 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.3. Updating forms in Aggregate

1. example_form_v1.0
2. example_form_v1.1

Note: You cannot change the question type or name, form id and title. Example: In above
form you cannot change the type from select_one to select_multiple or change name
from dept to department.

Note: When a user tries to get new blank forms, a form with updated version will be
selected by default in the list and will contain an additional message to indicate it’s an
update.

Both versions of the form will exist in the device of the user but only the newer one will be
visible on the list. Thanks to that the user will be able to edit forms he has started using
the older version and upload them to the server, but new forms will be started using the
newest available form version.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 457
Chapter 19. Tips and Best Practices

19.3.2 Replacing existing form

If you need to make deeper changes like changing question type, name, form id, form title
etc then you will need to create a new form with the required changes.
Once you will modify your form, the data you will collect will be stored under that new
form. However, you do not need to delete the previous form, instead, you may change the
name of the new form. For example, if you had form name as Example_form, the revised
form can be named as Example_form_1.1. Additionally, on your Aggregate restrict the
previous form by unchecking Downloadable and Accept Submissions options.

Warning: If you make changes like changing a question type or name with the same
form id and title and update the version, you won’t be able to re-upload the form.
Aggregate will reject the form upload with an error message.

19.4 Increasing Aggregate Field Length

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

By default, Aggregate’s datastore layer limits text values to 255 characters or less. If a
submission includes a value longer than 255 characters, those additional characters are not
saved in the database and no warning is shown. That means there is a risk of data loss
when using question types that save long text values such as geotrace, geoshape or select

458 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
19.4. Increasing Aggregate Field Length

multiple. This limitation exists for performance reasons, particularly for older versions of
MySQL.
It is possible to set the desired database field length for a particular question. This value can
go up to about 16000 UTF-8 characters but the datastore storage efficiency may get worse
as the value increases. If you go over 16000 characters, be sure to do an end-to-end test to
ensure the performance is acceptable.

Tip: Each geopoint is roughly 50 characters, so a geotrace or geoshape with a length of


16000 will store about 320 points.

In an XLSForm, the database field length is set from the bind::odk:length column. On
form upload, Aggregate will adjust the database field length of questions that have a whole
number in that column. Other questions will get a default length of 255.

XLSForm

Table 19.16: survey


type name label bind::odk:length
select_multiple opt_abc multi Select multi 500
geoshape shape Select an area 1000

Table 19.17: choices


list_name name label
opt_abc a A
opt_abc b B
opt_abc c C

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 459
Chapter 19. Tips and Best Practices

460 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTY

ODK BRIEFCASE

ODK Briefcase is a desktop application that runs on macOS, Windows, and Linux. It is
used for pulling, pushing, and exporting forms on ODK servers such as ODK Central and
ODK Aggregate. You can also use Briefcase to pull forms directly from ODK Collect.
With Briefcase you can:
• Pull forms from Collect, Central, Aggregate.
• Push forms to a Central or Aggregate server.
• Export data from forms to CSV files.
• Decrypt encrypted forms.
• Back up forms from servers.
• Transfer forms between servers.
• Work from a command line.
• Work offline.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 461
Chapter 20. ODK Briefcase

20.1 Learn more about Briefcase

• Setting Up ODK Briefcase


• Using ODK Briefcase

462 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYONE

SETTING UP ODK BRIEFCASE

Before you begin…


You must run Briefcase with Java 8.0.221 or higher. We recommend installing OpenJDK 11
LTS from AdoptOpenJDK.

1. Download the ODK Briefcase JAR file from GitHub.


Some browsers may warn that JAR files might harm your computer. Do not
worry, Briefcase when downloaded from our GitHub page is safe.
2. Double-click the downloaded JAR file or, from the command line, run java -jar
{path/to/ODK-Briefcase-vX.Y.Z.jar}
macOS will warn that Briefcase is from an unidentified developer. This is
normal and expected. Follow these instructions from Apple to open the file.
3. Follow the instructions to start using Briefcase

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 463
Chapter 21. Setting Up ODK Briefcase

464 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYTWO

BRIEFCASE AND AGGREGATE

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

ODK Briefcase and ODK Aggregate have complementary and overlapping features. For some
deployments, it makes sense to use one or the other. In other case, it makes sense to use
them together.
This page compares Briefcase and Aggregate, and explains their differences.

22.1 Briefcase

With Briefcase you can:


• Pull forms from Collect, Central, Aggregate.
• Push forms to a Central or Aggregate server.
• Export data from forms to CSV files.
• Decrypt encrypted forms.
• Back up forms from servers.
• Transfer forms between servers.
• Work from a command line.
• Work offline.

Note: Briefcase cannot be used to Push forms directly to Collect. However, this is not
needed as you can do this with adb.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 465
Chapter 22. Briefcase and Aggregate

22.2 Aggregate

With Aggregate you can:


• Host blank forms to be downloaded by Collect.
• Accept finalized form instances from Collect.
• Review and visualize submitted form data.
• Export submitted form data to CSV , KML, and JSON .
• Publish data to Google Sheets or JSON servers.

22.3 Notable Differences

• Aggregate supports export to KML and JSON. Briefcase does not.


• Aggregate can host blank forms for Collect users to download over the internet. Brief-
case cannot.
• Aggregate can receive form data from Collect over the internet. Briefcase cannot.
• When moving forms from Collect to Aggregate, form instances are ignored if they have
not been finalized. When using Briefcase, all form instances are transferred.
• Aggregate supports simple visualizations. Briefcase does not.
• Briefcase has a command line interface (CLI), while Aggregate does not. In addition to
using Briefcase from a terminal, the CLI can also be scripted. No comparable scripting
interface exists for Aggregate.
• Briefcase is a small and simple desktop application requiring very little setup and no
maintenance. Aggregate is a full-fledged server backed by an enterprise database.

466 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYTHREE

ODK AGGREGATE

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

ODK Aggregate is an open source Java application that stores, analyzes, and presents XForm
survey data collected using ODK Collect or other OpenRosa-compliant applications. It sup-
ports a wide range of data types, and is designed to work well in any hosting environment.
With Aggregate, data collection teams can:
• Host blank XForms used by ODK Collect or other OpenRosa clients
• Store and manage XForm submission data
• Visualize collected data using maps and simple graphs
• Export and publish data in a variety of formats
Aggregate can be hosted on cloud providers such as DigitalOcean, and Amazon Web Services,
or your own local or cloud server. There’s also a pre-configured virtual machine image that
is ready to deploy on any computer.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 467
Chapter 23. ODK Aggregate

23.1 Learn more about ODK Aggregate

• Setting Up ODK Aggregate


• Using ODK Aggregate
• Getting Started With ODK

468 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYFOUR

SETTING UP ODK AGGREGATE

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Before you get started


If you just want to explore ODK Aggregate, try the demo server.

24.1 Planning Your Aggregate Deployment

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

ODK Aggregate can be deployed to any local or cloud server that runs Tomcat, Java8, and
PostgreSQL (MySQL is supported too).
You can also use these guides for some specific cloud providers:
• DigitalOcean
• Amazon Web Services
There is also a fully set-up virtual machine that can be run in nearly any environment.
If you have highly-technical user, you can also try using:
• A Docker image
• A Docker Compose setup
Previous versions of Aggregate (v1.x) can be deployed in Google App Engine, but we strongly
recommend deploying Aggregate v2.x using any of the guides above.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 469
Chapter 24. Setting Up ODK Aggregate

You can also go without Aggregate altogether and use ODK Briefcase.
This document provides general advice for thinking through your deployment decisions.

24.1.1 Internet access

DigitalOcean and Amazon Web Services both require internet access. If you don’t have
consistent internet access, ODK Briefcase may be more appropriate.
Tomcat deployments can operate without internet access. In such an environment, Collect
would only be able to upload finalized forms after it connects to the network containing the
Tomcat deployment.

24.1.2 Computer skills

Custom Tomcat deployments in local or cloud servers, including the one described in the
Amazon Web Services guide, have a steep learning curve and require technical aptitude. At
a minimum you will be:
• changing network configuration
• selecting and using a website hosting service or specifying and configuring your own
server and network router(s)
• installing software
• ensuring that your site has proper power-failure and data-backup systems in place
If this level of systems administration skill is not available, you will have more success using
the DigitalOcean guide, which leverages a Cloud-Config stack that will do most of the heavy
lifting for you.

24.1.3 Component versions

ODK Aggregate should work with these minimum component versions. In most cases, newer
versions should also work.

� v1.4.13
Java 8
Tomcat 8.0
PostgreSQL 9.4
MySQL (not MariaDB) 5.7

470 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.1. Planning Your Aggregate Deployment

24.1.4 Ongoing support

• You should consider doing periodic backups of your data.


• If data security is a concern, you should have a system administrator or database
administrator periodically review logs and look for malicious activity.

24.1.5 Infrastructure architecture

In these docs we explain how to deploy a monolithic server with everything Aggregate needs
to run (Tomcat, PostgreSQL, SSL support), but there is a multitude of scenarios that you
might want to consider:
• You could deploy Aggregate on one machine and the database in a separate machine,
or even use a cloud database.
• You could have high-availability or an horizontal scalability option by using a load
balancer.
• You could provide SSL security with a load balancer or proxy.
If you are considering alternative architectures for your specific needs, we recommend you
ask for help in the support forum.

24.1.6 Dataset size

You have to take into account the size of the data set you need to store, which grows not
only with the number of submissions but also with the structure of the forms. Forms with
more media attachments will produce larger data sets.
When sizing your infrastructure, take into account:
• Greater storage capacity usually comes associated with higher costs.
• Storage is usually hard to scale. Try to start with enough capacity for your data set
and add a little bit extra.
• The computing power doesn’t necessarily have to scale with the data set size.

Note: For historical reasons, individual text database fields are capped at a length of 255
by default. If you intend to collect text data longer than 255 characters (including using
types geotrace, geoshape or select multiple), your forms should specify database field lengths
greater than 255.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 471
Chapter 24. Setting Up ODK Aggregate

24.1.7 Data locality

Cloud providers have servers located all over the world. Most of these providers will let you
choose where your server should be located.
Depending on the sensitivity of the data and specific storage rule, regulations, or restrictions
of your country or organization, the server infrastructure may not have all necessary locality
guarantees or security precautions.

24.1.8 Secure and protected data

If you need to prevent eavesdroppers from seeing your data as it is transmitted to your ODK
Aggregate instance, you need to do one of the following:
• only connect to ODK Aggregate from within your organization’s network (when the
submitting devices are on your premises)
• obtain an SSL certificate and install it on your server (a certificate is required to secure
transmissions over https)
• use Encrypted Forms
Encrypted forms can be used in conjunction with either of the first two suggestions.
If you are not using encrypted forms and are handling sensitive data, a computer security
specialist should review your system and your security procedures.

Note: Use of an SSL and https is recommended for any deployment accessed from the
internet.

24.1.9 Availability

Decide the availability of your server depending on how frequently you want to update and
upload forms. If you do need a high-availability server, you need to talk to your Internet
Service Provider (ISP) as to their availability guarantees.

24.1.10 Data loss

Your tolerance to data loss will impact your backup schedule and your server hardware.
Invest in a system based on your tolerance to data loss. Seek technical assistance for these
requirements.

472 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

24.2 Installing Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

24.2.1 Installing on Tomcat

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Apache Tomcat is an open source Java web server that can be used to serve ODK Aggregate.
This document guides you through the installation and initial setup of a self-hosted instance
of ODK Aggregate, running on Tomcat with a PostgreSQL, or MySQL database server.
”Self-hosted” could mean on your own hardware or on a cloud-based server.
If you’re planning on hosting your server on a cloud provider, you can use these provider-
specific guides:
• DigitalOcean (recommended)
• Amazon Web Services
• Google Cloud
• Microsoft Azure

Note:
• Local hosting implies that you are taking ownership of the off-site back up and restora-
tion of your data and are documenting the steps necessary to return your systems to
operation in circumstances that might include a full hardware failure or the destruction
of your facility. You must also plan for the security of your data and systems.
• Local hosting requires that you configure your network routers. It is recommended
to seek assistance from your local computer technical support community before pro-
ceeding. The set-up of the ODK Aggregate web server and database are very easy in
comparison.

Considerations before you begin

Please, read the Aggregate deployment planning guide before continuing.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 473
Chapter 24. Setting Up ODK Aggregate

Database systems

ODK Aggregate works with any of these database servers:


• PostgreSQL
PostgreSQL is the recommended database server for Aggregate.
• MySQL
Although MySQL is supported, it’s not actively being tested during the release cycle.
MySQL tables have a row size limit that will affect performance for very large forms.

Installation procedure

1. Install Java 8.0.221 or higher. We recommend using OpenJDK 11 LTS from Adop-
tOpenJDK:
Windows
macOS
Ubuntu
Download OpenJDK 11 LTS and run it as administrator.
Download OpenJDK 11 LTS and install it.

sudo apt-get install openjdk-11-jre

2. Ensure that the installed Java bin directory is in the PATH environment variable.
3. Install Apache Tomcat 8.5:
Windows
macOS
Ubuntu
Download the Windows Service installer, and run it as administrator.
If you have Homebrew, run:

brew install tomcat@8.5

sudo apt-get install tomcat8 tomcat8-common tomcat8-user tomcat8-admin

4. Configure your server and network devices so that laptops or Android devices connect-
ing to the internet from an external access point can access your server.

474 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

If your organization has a network or systems administrator, contact them for


assistance. The steps for this are:
• configure your server firewall to allow access
• make your server visible on the internet (optional)
• establish a DNS name for the server
5. Obtain and Install an SSL certificate if you need secure https access.
6. Install PostgreSQL:
Windows
macOS
Ubuntu
Download the PostgreSQL 10.6 Windows installer, and run it as administrator.
Download the PostgreSQL 10.5 Postgres.app DMG installer, and open it.

sudo apt-get install postgresql-10

7. Install ODK Aggregate. Select the latest release for your operating system.
The installer will guide you through configuring ODK Aggregate for your setup.
The installer will produce a WAR file (web archive) containing the config-
ured ODK Aggregate code, a create_db_and_user.sql script for creating the
database and user that ODK Aggregate will use to access this database, and a
Readme.html file with instructions on how to complete the installation.

Tip:
• When asked for the fully qualified hostname of the ODK Aggregate server,
you should enter the DNS name you established above.
• The install also asks for a database name, user and password. The user
should not be postgres (PostgreSQL), or root (MySQL).
• ODK Aggregate will use this user when accessing this database (and it will
only access this database).
• By specifying different databases and users, you can set up multiple ODK
Aggregate servers that share the same database server, store their data in
different databases, and operate without interfering with each other.
• If you are upgrading to a newer version of ODK Aggregate, as long as you
specify the same database name, user and password, you do not need to
re-run the create_db_and_user.sql script.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 475
Chapter 24. Setting Up ODK Aggregate

24.2.2 Installing on DigitalOcean (recommended)

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Warning: To use this setup, you must able to link a domain name to the machine’s
IP address. If you don’t own a domain, services such as FreeDNS offer free sub-domains
under a range of domains.

Tip: If you have not already created a DigitalOcean account, use our referral link to do so:
https://m.do.co/c/39937689124c.
DigitalOcean will give you $100 of credit to spend during the first 60 days so that you can
try things out. Once you have spent $25 with them, we’ll get $25 to put towards our hosting
costs.

Create your Droplet

1. Log into DigitalOcean and create a new Droplet.


2. Select the distribution for your new Droplet: Select the option 18.04.x x64 from the
Ubuntu box.

476 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

3. Select a size fit for your intended usage. The $5 Standard Droplet should be enough
for light Aggregate use. If you find yourself needing more, DigitalOcean makes it easy
to resize to a bigger Droplet.
4. If you would like automatic weekly backups, enable them.
5. You will not need block storage.
6. Select a datacenter region physically close to where data collection is going to happen.
7. Under Select additional options, check the User data checkbox. Copy and paste the
contents of this Cloud-Config script.

8. In the Choose a hostname section, enter the domain name (e.g., your.domain). This
hostname will be used by the Cloud-Config script to configure your server’s HTTPS
support.
9. You will not need to add public SSH keys (unless you know what that is and you want
to).
10. Click on the Create button. The Droplet takes a few seconds, the actual Aggregate
installation will take up to 10 minutes to complete.

Set up your domain

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 477
Chapter 24. Setting Up ODK Aggregate

Tip: DigitalOcean Droplets use IP addresses which can change if you destroy the machine.
To ensure your Aggregate install will always be reachable using the same IP address, use a
Floating IP by following these instructions.

1. Once the Droplet is running, take note of its public IP address (e.g., 12.34.56.78) and
set a DNS A record pointing to it.
If you own a domain, check your domain registrar’s instructions. If you don’t own a
domain, we recommend using FreeDNS to get a free sub-domain.
Your domain’s TTL setting will affect to how much time you will have to wait until
you can proceed to the next step. If your provider gives you the option of setting a
TTL, use the lowest value you can.
2. Open a web browser, and periodically check the domain until you see the Aggregate
website. You won’t be able to continue the install until you see the website load.

Enable HTTPS

1. From the DigitalOcean Control Panel, click the name of your droplet, then select Access
from the left navigation. Click the Launch Console button to open a web-based console
session.
2. When the console opens, click the console screen, and at the login prompt, enter the
user: root. Your password will be the root password that DigitalOcean emailed you.
If you do not have the root password, click the name of your droplet, select
Access from the left navigation and choose Reset the root password so that
a password gets emailed to you.
You may also login over SSH using the ssh root@your.domain.
3. Once you are logged in, run sudo certbot run --nginx --non-interactive
--agree-tos -m YOUR_EMAIL --redirect -d YOUR_DOMAIN.
Be sure to replace YOUR_EMAIL and YOUR_DOMAIN with your email
address and your domain.
Lets Encrypt uses the email you provide to send notifications about expira-
tion of certificates.

Log into Aggregate

1. Go to https://your.domain and check that Aggregate is running.


2. Click Sign in with Aggregate password to login with the default username and password.

478 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

username: administrator
password: aggregate
3. Change the administrator account’s password!

24.2.3 Installing on Amazon Web Services

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Warning: To use this setup, you must able to link a domain name to the machine’s
IP address. If you don’t own a domain, services such as FreeDNS offer free sub-domains
under a range of domains.

Tip: Make sure you have selected the availability zone where you want to perform your
actions. You can choose the availability zone using the dropdown menu at the top-right
corner of the AWS console website. Choose a region that’s close to the location where data
is going to be collected.

Create a VPC

1. Go to the VPC Dashboard.


2. Click on Launch VPC Wizard.
3. Follow the wizard for the VPC with a Single Public Subnet configuration.
4. Enter aggregate-vpc (or your desired name) in the VPC Name field.
5. Click on Create VPC.

Create a security group

1. Go to the VPC - Security Groups tab.


2. Click on Create security group.
3. Follow the wizard for the VPC with a Single Public Subnet configuration.
4. Enter aggregate-sg (or your desired name) as the name and description.
5. Select the VPC you previously created.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 479
Chapter 24. Setting Up ODK Aggregate

6. Click on Create.
7. Click on the newly created security group from the list, click on the Inbound rules tab,
the Edit rules.
8. Add the following rules to allow SSH, HTTP, and HTTPS traffic.

Type Source
SSH Anywhere
HTTP Anywhere
HTTPS Anywhere

9. Click on Save rules.

Create an IAM role

The EC2 machine needs an IAM role to query its tags.


1. Go to the IAM - Roles tab.
2. Click on Create role.
3. Select the AWS service box, and click on the EC2 link.
4. Click on Next: Permissions.
5. Search for AmazonEC2ReadOnlyAccess, and select it.
6. Click on Next: Tags and do nothing.
7. Click on Next: Review.
8. Enter aggregate-role (or your desired name) as the name.
9. Click on Create role.

Create an EC2 machine

1. Go to the EC2 Dashboard.


2. Click on Launch instance.
3. Search for the Ubuntu Server 18.04 LTS AMI.
4. Select the 64-bit (x86) option and click on Select.
5. Select the instance type you want to use.
A minimum setup is a t2.small instance type (1 vCPU, 2GiB RAM), but you
should review your requirements and choose a bigger instance type according
to your needs.

480 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

6. Click on Next: Configure Instance Details.


7. Select the VPC you previously created in the Network dropdown.
8. Select Enable in the Auto-assign Public IP dropdown.
9. Select the IAM role you previously created in the IAM role dropdown.
10. Toggle the Advanced Details section and copy and paste the contents of this Cloud-
Config script.
11. Click on Next: Add Storage and edit the storage settings.
A minimum setup is 30 GiB of storage, but you should review your requirements and
adjust the value of the Size (GiB) field according to your needs.
12. Click on Next: Add Tags.
13. Add a aggregate.hostname key with the domain name as the value (e.g., your.domain).
This hostname will be used by the Cloud-Config script to configure your machine’s
HTTPS support.
14. Click on Next: Configure Security Group.
15. Select an existing security group and select the security group you previously created.
16. Click on Review and Launch and after review, click on Launch.
17. You will be offered the option of using an existing key pair or creating one. It’s very
important that you follow the dialog’s instructions carefully to be able to access your
machine once it’s created.
18. When you’re ready, click on Launch instances.

Set up your domain

Tip: EC2 machines use IP addresses which can change if you stop and start (but not
reboot) the machine. To ensure your Aggregate install will always be reachable using the
same IP address, use an Elastic IP by following these instructions.

1. Go to the EC2 - Instances tab and find your machine.


2. Take note of the IPv4 Public IP address (e.g., 12.34.56.78) and set a DNS A record
pointing to it.
After clicking on the instance from the list, look for under the Description
tab at the bottom of the window. The IPv4 Public IP field is in the right
column.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 481
Chapter 24. Setting Up ODK Aggregate

If you own a domain, check your domain registrar’s instructions. If you don’t
own a domain, we recommend using FreeDNS to get a free sub-domain.
Your domain’s TTL setting will affect to how much time you will have to
wait until you can proceed to the next step. If your provider gives you the
option of setting a TTL, use the lowest value you can.
3. Open a web browser, and periodically check the domain until you see the Aggregate
website. You won’t be able to continue the install until you see the website load.

Enable HTTPS

1. Connect to your machine via SSH using ssh -i /path/to/the/key.pem


ubuntu@your.domain.
Make sure your PEM key pair file has the correct file permissions.
2. Once you are logged in, run sudo certbot run --nginx --non-interactive
--agree-tos -m YOUR_EMAIL --redirect -d YOUR_DOMAIN.
Be sure to replace YOUR_EMAIL and YOUR_DOMAIN with your email
address and your domain.
Lets Encrypt uses the email you provide to send notifications about expira-
tion of certificates.

Log into Aggregate

1. Go to https://your.domain and check that Aggregate is running.


2. Click Sign in with Aggregate password to login with the default username and password.
username: administrator
password: aggregate
3. Change the administrator account’s password!

24.2.4 Installing on Google Cloud

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

482 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

Warning: To use this setup, you must able to link a domain name to the machine’s
IP address. If you don’t own a domain, services such as FreeDNS offer free sub-domains
under a range of domains.

Tip: If you are new to Google Cloud, you will need to create a Google Cloud Platform
project and make sure billing is enabled.

Create an instance

1. Go to the GCP Dashboard.


2. Click on Create.
3. In the Name text box, enter aggregate (or your desired name).
4. Select the desired region and zone.
Choose a region that’s close to the location where data is going to be col-
lected.
5. Select the instance type you want to use.
A minimum setup is a small instance type (1 vCPU, 1.7 GB of memory),
but you should review your requirements and choose a bigger instance type
according to your needs.
6. Click on Change under the Boot disk section.
7. Select Ubuntu 18.04 LTS.
8. Set the desired storage size for your VM, and click Select.
A minimum setup is 30 GB of storage, but you should review your require-
ments and adjust the value of the Size (GiB) field according to your needs.
9. Under the Firewall section, check Allow HTTP traffic, and Allow HTTPS traffic.
10. Expand the Management, security, disks, networking, sole tenancy section.
11. In the Management tab, under Automation, copy the contents of this startup script
into the Startup script text box.
12. In the Networking tab, set the Hostname with the domain name (e.g., your.domain)
you want to use for Aggregate. This hostname will be used by the startup script to
configure your instance’s HTTPS support.
13. Click on Create.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 483
Chapter 24. Setting Up ODK Aggregate

Set up your domain

Tip: GCP instances use IP addresses which can change if you delete the instance. To
ensure your Aggregate install will always be reachable using the same IP address, use a
static IP address by following these instructions.

1. Go to the GCP - VM Instances page and find your instance.


2. Take note of the IP address (e.g., 12.34.56.78) in the External IP column and set a
DNS A record pointing to it.
If you own a domain, check your domain registrar’s instructions. If you don’t
own a domain, we recommend using FreeDNS to get a free sub-domain.
Your domain’s TTL setting will affect to how much time you will have to
wait until you can proceed to the next step. If your provider gives you the
option of setting a TTL, use the lowest value you can.
3. Open a web browser, and periodically check the domain until you see the Aggregate
website. You won’t be able to continue the install until you see the website load.

Enable HTTPS

1. In GCP - VM Instances page, SSH into your VM clicking the SSH button in the
External IP column.
2. Once you are logged in, run sudo certbot run --nginx --non-interactive
--agree-tos -m YOUR_EMAIL --redirect -d YOUR_DOMAIN.
Be sure to replace YOUR_EMAIL and YOUR_DOMAIN with your email
address and your domain.
Lets Encrypt uses the email you provide to send notifications about expira-
tion of certificates.

Log into Aggregate

1. Go to https://your.domain and check that Aggregate is running.


2. Click Sign in with Aggregate password to login with the default username and password.
username: administrator
password: aggregate
3. Change the administrator account’s password!

484 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

24.2.5 Installing on Microsoft Azure

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Warning: To use this setup, you must able to link a domain name to the virtual
machine’s IP address. If you don’t own a domain, services such as FreeDNS offer free
sub-domains under a range of domains.

Create a VPC

1. Go to the Virtual machines dashboard.


2. Click on Add.
3. Ensure you have a Subscription and a Resource group. If no resource group exists,
create one called Aggregate (or your desired name).
4. In the Virtual machine name text box, enter Aggregate (or your desired name).
5. Select the desired region.
Choose a region that’s close to the location where data is going to be col-
lected.
6. In Image, select Ubuntu 18.04 LTS.
7. Select Size of VM you want to use.
A minimum setup is a B1ms type (1 vcpu, 2 GB of memory), but you should
review your requirements and choose a bigger VM according to your needs.
9. Set a Authentication type to Password and enter a secure Username and Password.
Alternatively, use a SSH public key if you know what that is and how to use
it.
10. Under Public inbound ports, select Allow selected ports.
11. In Select inbound ports, select HTTP, HTTPS, and SSH.
12. Click Next : Disks >.
13. Click Create and attach a new disk.
14. Select Disk type and Size of disk you want to use.
A minimum setup is a Standard SSD disk type and 30 GiB size, but you should review
your requirements and adjust appropriately.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 485
Chapter 24. Setting Up ODK Aggregate

15. Click on the Advanced. It’s in the tabs at the top of the screen.
16. In the Cloud init text box, paste the contents of this Cloud-Config script.
17. Click Next : Tags >.
18. Add Name of aggregate.hostname and a Value of your domain (e.g., your.domain).
This hostname will be used by the Cloud-Config script to configure your VM’s HTTPS
support.
19. Expand the Next: Review + create, then Create.

Set up your domain

Tip: Azure VPCs use IP addresses which can change if you destroy the VPC. To ensure
your Aggregate install will always be reachable using the same IP address, use a static IP
by following these instructions.

1. In Virtual machines dashboard, find your VM from the list. Click on it and find the
value of the Public IP address field in the overview section.
2. Take note of the IP address (e.g., 12.34.56.78) and set a DNS A record pointing to it.
If you own a domain, check your domain registrar’s instructions. If you don’t
own a domain, we recommend using FreeDNS to get a free sub-domain.
Your domain’s TTL setting will affect to how much time you will have to
wait until you can proceed to the next step. If your provider gives you the
option of setting a TTL, use the lowest value you can.
3. Open a web browser, and periodically check the domain until you see the Aggregate
website. You won’t be able to continue the install until you see the website load.

Enable HTTPS

Warning: Azure VMs seem to be slower to install software than other cloud providers.
If you are having trouble running the commands in this step, wait 15 minutes and try
again.

1. Connect to your VM via SSH.


2. Once you are logged in, run sudo certbot run --nginx --non-interactive
--agree-tos -m YOUR_EMAIL --redirect -d YOUR_DOMAIN.

486 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

Be sure to replace YOUR_EMAIL and YOUR_DOMAIN with your email


address and your domain.
Lets Encrypt uses the email you provide to send notifications about expira-
tion of certificates.

Log into Aggregate

1. Go to https://your.domain and check that Aggregate is running.


2. Click Sign in with Aggregate password to login with the default username and password.
username: administrator
password: aggregate
3. Change the administrator account’s password!

24.2.6 Installing the Virtual Machine

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

This document provides instructions for installing ODK Aggregate using the Virtual Machine
(VM) and VirtualBox.

Setting up the VM

1. Download and install VirtualBox.


2. Download the latest Aggregate VM from the GitHub releases page and unzip the file.
3. Double-click the OVA file inside the zip to let VirtualBox import the VM. Accept the
default settings.
4. After the import completes, start the VM. Select it with your mouse and click on the
Start button on the VirtualBox top toolbar. A new black and white window will open.
5. After the VM starts, wait for Welcome to ODK Aggregate VM message to appear.
6. Do not log into the screen of the VM. Instead, on your computer, open a web browser.
7. Go to the web address shown in the VM screen. (Usually http://localhost:10080.) If
everything worked, you will see the Aggregate login screen.
8. Sign in with Aggregate password

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 487
Chapter 24. Setting Up ODK Aggregate

username: administrator
password: aggregate

9. Aggregate will remind you to change your administrator user’s password. Please choose
a secure password!

Tip: Once VirtualBox has imported the VM, the zip file and the OVA file can be deleted.

Note:
• Read the Running your virtual machine manual page to learn more about working
with VirtualBox and your Aggregate VM.
• Windows: if you get an VirtualBox error message with ”File is busy” or ”File access
error” after launching the VM, it is likely due to improper unzipping or write permis-
sions. Try right-clicking the zip file, then select ”Extract All” and save the files to a
folder on the Desktop.
• Linux: if you get a VirtualBox error message about ”PAE: Unable to boot”, make sure
VirtualBox has PAE/NX enabled. That setting is usually under System/Processor.

Securing the VM

The Aggregate VM is configured with a default root user password which is not secure.
Before using the VM with important data, we recommend you log in and change the default
password.
1. Start the VM. When the VM has finished booting up, you will be prompted to log into
the VM.
2. Click on the screen to capture your mouse and keyboard.
3. Log into the command line interface with the following credentials:
username: root
password: aggregate
4. You will be forced to change the default password the first time you login. Please
choose a secure password!
5. Once you have logged in, you can exit the command line interface with the exit
command.

488 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.2. Installing Aggregate

Note: Make sure you understand how VirtualBox captures your mouse and keyboard and
how to release them.

Connecting to the VM from external apps

The VM defaults to a NAT network adapter, so you will only be able to connect to it from
your computer. This is the default behavior because it is the safest configuration.
If you’d like to connect to the VM from an external device (for example, ODK Collect on
your phone or ODK Briefcase on another computer), you must set a fully qualified domain
name (FQDN) or globally accessible address.

Tip: Aggregate’s form download (but not form listing) relies on the FQDN. If you want to
use Collect and Briefcase to interact with Aggregate, you must set the FQDN.

To set the FQDN, do the following:


1. Secure the VM .
2. Change the VM’s network adapter settings in VirtualBox from NAT to Bridged and
reset/reboot the VM.
3. After the reset/reboot, the VM will behave like any other machine on your network
and get an IP address from your router. The IP address will be shown to you after the
Welcome to ODK Aggregate VM message.
4. Log into the command line interface of the VM and run the aggregate-config script
to set a fully qualified domain name (FQDN) using the IP address that was shown to
you (e.g., 192.168.5.2).

aggregate-config --fqdn 192.168.5.2 --http-port 8080 --https-port 8443␣


,→--net-mode bridge

5. After the configuration, use your host computer or any other computer on your network
to log into Aggregate at the FQDN and port (e.g., http://192.168.5.2:8080).

Note: Learn more about VirtualBox’s networking options.

See also:
Planning Your Aggregate Deployment

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 489
Chapter 24. Setting Up ODK Aggregate

24.3 Upgrading Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

24.3.1 Need for Upgrading

It is important to upgrade to newer ODK Aggregate versions as they come out. You don’t
need to do this immediately, but this should be something you do at least once a year.

Security vulnerabilities

The ODK developers are constantly upgrading the libraries we use with newer, safer versions.
The older your software, the greater the number of vulnerabilities in it.

Performance improvements

As we find performance issues and address them, the Aggregate gets faster and cheaper to
run.

Enhanced capabilities

ODK JavaRosa, the underlying form rendering library is updated about annually. Those
updates add new functions, features, and occasionally data types. New features are slowly
added to ODK Aggregate, too.
To use these newer features, keep your Aggregate installation up to date.

24.3.2 Determining your Aggregate version

Aggregate shows a notice about the deployed version at the bottom left corner of all the
pages. The version notice will be clickable if there’s an update available.
Instructions for older versions:
If you are able to log onto the server as a Site Administrator, the ODK Aggregate version is
displayed at the top of the Preferences sub-tab under the Site Admin tab.
If you are unable to log onto your server, you will need to search for the version in the
application logs. To do that:
1. Open a browser to https://appengine.google.com.

490 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.3. Upgrading Aggregate

2. Choose the project id for your ODK Aggregate server by clicking on the project drop-
down in the top left corner.

3. Search logs in the search box and select logging.

4. In the filter text box paste this text : afterPropertiesSet and hit enter.
5. Expand the list of logs and find the log which shows the version of Aggregate. It will
be of the following format:

13:24:54.806 org.opendatakit.common.security.Realm afterPropertiesSet: Version:␣


,→v1.4.15 Production (Realm.java:51)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 491
Chapter 24. Setting Up ODK Aggregate

24.3.3 General steps for upgrading

1. Disable all submissions to ODK Aggregate, in the Form Management tab.


2. Use ODK Briefcase to pull a copy of all data to your computer.
3. Log onto your server to confirm that it is still functioning.
4. Determine your current version number.
5. Download the next ODK Aggregate version and upgrade to that version. Find
previous versions here.
Do not simply upgrade from an old version of Aggregate to the latest version. It
is important to upgrade sequentially through versions, instead of trying to upgrade
directly to the latest version from an older one.
Some versions will require manual changes upon upgrade. Complete notes about up-
grading can be found in each version’s release notes.
6. Log onto your server to confirm that it is still functioning.
7. Repeat the steps 4-7 until you have upgraded to the current version.
8. Enable submissions to ODK Aggregate via the Form Management tab.

Tip: You need to know the exact instance name that was used in prior installations for your
username and password to continue to work. If you add a space or change capitalization or
spelling, the passwords will be invalid (you just need to re-run the installer with the correct
string to correct the problem).

24.3.4 Upgrading DigitalOcean deployments

Please, refer to the Aggregate Cloud-Config updates guide

492 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.4. Backing Up Aggregate

24.4 Backing Up Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

24.4.1 Backup and restore forms and submissions with Briefcase

You can use ODK Briefcase to backup your forms and submissions by pulling them from
Aggregate, and restore them by pushing them back to Aggregate.

Warning: Please, be aware that this procedure doesn’t backup your server’s configura-
tion, users, exported forms, publisher configurations, and other important settings that
you might still want to account for.

24.4.2 PostgreSQL backup & restore

Backup

1. Stop running Tomcat. This step, although optional, is recommended to produce full
and coherent database dumps.
2. Produce a database backup file:
Windows
macOS and Linux:

pg_dump.exe [ dbname ] > [ backup file location ]

pg_dump [ dbname ] > [ backup destination ]

3. Start Tomcat if you stopped it on the first step.


You could get some errors depending on your particular PostgreSQL users and server con-
figuration. Refer to the pg_dump documentation for more information on the options you
can add to this command.

Restore

1. Stop running Tomcat.


2. Load the backup file:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 493
Chapter 24. Setting Up ODK Aggregate

Windows
macOS and Linux:

psql.exec -f [ backup file location ] [ dbname ]

psql -f [ backup file location ] [ dbname ]

3. Start Tomcat.
You could get some errors depending on your particular PostgreSQL users and server con-
figuration. Refer to the psql documentation for more information on the options you can
add to this command.

24.4.3 MySQL backup & restore

Backup

1. Stop running Tomcat. This step, although optional, is recommended to produce full
and coherent database dumps.
2. Produce a database backup file:
Windows
macOS and Linux:

mysqldump.exe [ dbname ] > [ backup file location ]

mysqldump [ dbname ] > [ backup destination ]

3. Start Tomcat if you stopped it on the first step.


You could get some errors depending on your particular MySQL users and server configura-
tion. Refer to the mysqldump documentation for more information on the options you can
add to this command.

Restore

1. Stop running Tomcat.


2. Load the backup file:
Windows
macOS and Linux

494 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
24.4. Backing Up Aggregate

mysql.exec [ dbname ] < [ backup file location ]

mysql [ dbname ] < [ backup file location ]

3. Start Tomcat.
You could get some errors depending on your particular MySQL users and server configu-
ration. Refer to the mysql documentation for more information on the options you can add
to this command.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 495
Chapter 24. Setting Up ODK Aggregate

496 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYFIVE

USING ODK AGGREGATE

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

25.1 Managing Forms in Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

You can add, download and delete forms, export data into useful formats, publish data into
another service, manually upload submissions and view the published data. ODK Aggregate
provides all these options under the Form Management tab.

25.1.1 View blank form list

Click on Forms list tab to see a list of all your forms.


From here, you can add new forms, delete forms, download forms as well as restrict submis-
sions for a form.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 497
Chapter 25. Using ODK Aggregate

Blank form info in list

In addition to the functional columns described below, the form list displays the following
information about each form.
• Form Id is the unique name for the form.
• Media Files is the count of media files associated with the form.
• User is the user who uploaded the form.

25.1.2 Adding New Forms

Under the Form list tab, you will see Add New Form button to upload a new form definition
to ODK Aggregate.

When you click on it a box will open asking for details of the form. Form Definition is
required and Media File(s) is optional. Choose the .xml file that will be used. You can also
choose the appropriate media files for the form.

498 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.1. Managing Forms in Aggregate

25.1.3 Viewing and downloading forms

From the form list, click on form’s Title to view the XForm (the actual XML file). You can
then download the file by clicking on Download XML in the Form XML Viewer.

Note: Please, be aware that Aggregate doesn’t store the original uploaded blank form.
Instead, it rebuilds a blank form with what’s stored in the database. This implies that there
could be some slight differences:
• All blank forms downloaded from Aggregate will include an XML comment with the
build date.
• Any left padding with zeroes will be lost on the form’s version number if it was originally
present (000042 will become 42).

25.1.4 Disabling or enabling downloading of a form

To disable or enable the ability of Collect or other clients to download forms, toggle the
checkbox in the Downloadable column of the blank forms list.

25.1.5 Disabling or enabling submission of a form

To disable or enable the ability of Collect or other clients to submit completed instances of
a form, toggle the checkbox in the Accept Submissions column of the blank forms list.

25.1.6 Deleting a blank form

Click on the Delete button for the form in the blank forms list.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 499
Chapter 25. Using ODK Aggregate

25.1.7 Exporting form data

Click on Export option in the form list to export form into useful formats and choose the
format in which you want to export data. You can also choose a filter which you have saved
for the form to export only a certain subset of the form. Details on exporting data are given
in the data transfer section.

25.1.8 Publishing form data

Click on Publish option in the form list to publish the form into another service. You can
choose where you want to publish data and which data you want to publish. Details on
publishing data are given in the data transfer section.

Viewing published data

You can get a view of the published data you have created for a particular form by clicking
on Published Data.

• Select the form corresponding to the published data in the Form dropdown.
• Read the message that appears and click on Purge Published Data.
• Created By shows the email of the user who created the published file.
• Status can be ACTIVE (the file is ready to view) or ESTABLISHED (something went
wrong in the process of exporting.)
• Start Date shows the time when you finished filling out the Publish form.
• Action is based on your selection of upload only, stream only, or both in the Publish
form.
• Type shows the type you choose to publish your data to.
• Owner shows the owner of the published data.
• Name is the place where you published your data.
• Select delete box in the Delete column if you want to delete your published file.

500 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.1. Managing Forms in Aggregate

25.1.9 Managing submissions manually

You can manually upload submissions for a form and check incomplete submissions under
the Submission Admin tab.

Submitting forms directly

To manually upload form submissions, click on Manually upload submission data.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 501
Chapter 25. Using ODK Aggregate

Note: Submissions in the Collect app are located under the /odk/instances directory on
the phone’s SD card. This directory will contain subdirectories with names of the form in
the format formID_yyyy-mm-dd_hh-MM-ss. Within each of these subdirectories are the sub-
mission data file (formID_yyyy-mm-dd_hh-MM-ss.xml), and zero or more associated media
files (images, audio, video) associated with this submission.

Note: If you upload a submission, but fail to upload all media attachments, it places
the submission in the incomplete submissions bucket. While it resides there, it won’t be
published to external servers or downloadable via ODK Briefcase.

Removing form submissions

To remove a form submission, select the form in the Form dropdown and click on Purge
Submission Data.

Incomplete form submissions

To see a list of incomplete submissions for a particular form under the Incomplete Submissions
list.

25.2 Working with Submitted Data in Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

You can view the data submitted from ODK Collect here. You can filter the submissions,
visualize them using pie chart, bar graph or map, export the submissions into useful formats
and publish the submitted data into another service. You can also view all the exported
submissions. ODK Aggregate provides all these options under the Submissions tab.

25.2.1 Filtering Submissions

Submissions from ODK collect can be filtered to view or hide a specific subset of data by
creation of filters. Filters give you the ability to see a subset of your data. You can have a
single filter as well as multiple filters. If you have multiple filters applied at once, then you

502 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.2. Working with Submitted Data in Aggregate

have a filter group. You can create and apply filters by using the options under the Filter
Submissions tab.
You can create a single or multiple filters depending on the subset of data you want to view
or hide. Creating a filter like Display Rows where column Gender EQUAL male specifies
that you want to get a list of all rows where gender column has value as male i.e you want
to obtain information about all male people in your data. Unless the filter is saved, it is
temporary. You can save a filter to make it permanent. Any filter can be deleted if it is no
longer needed.
Various options under this tab can be used as follows:
• Click on Add Filter to add filter to the data. In the Create filter to dropdown, Display
or Hide will specify whether you will be selecting data to show or hide and Rows or
Columns will specify whether you will be working with the rows or columns of the
table.

If you select Rows specify a condition you want to apply in the where box.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 503
Chapter 25. Using ODK Aggregate

If you selected Columns specify the columns you wish to display or hide in the titled box.

• Click on Save to save the filter or filter group for future use. Clicking on Save As allows
you to give a name to the filter or filter group.
• Click on Delete to delete a filter or filter group.

504 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.2. Working with Submitted Data in Aggregate

• You can check the Display Metadata checkbox to display or hide metadata.

Note: Metadata provides information about the submissions. There will be information
such as date submitted, if the data is complete, version numbers, and id numbers.

25.2.2 Visualizing Submissions

ODK Aggregate provides a quick means for basic data visualization. This Visualize func-
tionality is meant to provide a quick means to view early data results in meaningful ways
but is not meant to provide complex data analysis functionality. You can view your data in
bar graph, pie chart or on a map.
In both Pie chart and bar graph visualization you can either count the number of times
a unique answer occurs in a specified column or calculate sum of values in one column
grouped by a value in another column. You can choose a column that you want to map in
map visualization.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 505
Chapter 25. Using ODK Aggregate

Click on Visualize to visualize the submitted data. Select bar graph, pie chart or map in the
Type dropdown. Further options are described as follows:
• If you choose Pie Chart, choose whether you would like to count or sum data:
– If you select Count option, then select the column in which you want to apply
this.
– If you select Sum option, then select the column of values that you want to add
and another column that you want to use to group the numbers.
– Then click on Pie It to get the Pie Chart.

• If you choose Bar Graph, you have the same options as that in case of Pie Chart.
Choose the option you want to use and then click on Bar It to get the Bar Graph.

506 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.2. Working with Submitted Data in Aggregate

• If you choose Map, select a column that you want to map in the GeoPoint to Map
dropdown. Click on Map It to get the map. You can click on a point to view a balloon
with the other information supplied in the table.

25.2.3 Exporting Submissions

Click on Export option to export submitted data into useful formats and choose the format
in which you want to export data. You can also choose a filter which you have saved earlier
to export only a certain subset of data. Details on exporting data are given in the data
transfer section.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 507
Chapter 25. Using ODK Aggregate

25.2.4 Publishing Submissions

Click on Publish option to publish the submitted data into another service. You can choose
where you want to publish data and which data you want to publish. Details on publishing
data are given in the data transfer section.

25.2.5 Viewing Exported Submissions

You can to view the list of exported files under the Exported Submissions tab.

508 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.3. Administering Aggregate

• File Type specifies whether file is .csv or .kml or .json file.


• Status will state whether the file being made is in progress, or is now available for
viewing.
• Time Completed shows the time when the Export task is complete and the file is ready.
• Click on the link in Download File to see your exported file.
• Select delete box in the Delete column if you want to delete your exported file.

25.3 Administering Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Click the Log In link in the upper right corner of the screen to be presented with the Log
onto Aggregate screen. Choose the Sign in with Aggregate password button and enter the
super-user username you specified within the installer. The initial password for this account
is aggregate. When you log in, Site Admin will be visible to you.

Tip: When signing in with this method, if you do not enter the password correctly, you
may need to close all your browser windows and quit your browser before you can try again.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 509
Chapter 25. Using ODK Aggregate

Warning: If the instance name of the server changes (the installer asks for this name),
then the passwords for all ODK Aggregate usernames will no longer be valid and the
super-user username’s password will be reset to aggregate. In this case, you should log
in, change the super-user’s password, and change the passwords for all of your ODK
Aggregate usernames.

25.3.1 Permissions

Warning: Remember to change the default password of your super-user account. Oth-
erwise, anyone can take complete control of your server!

You can manage the credentials to access Aggregate in the Site Admin > Permissions sub-
tab.
Privileges are as follows:
• Data Collector: able to download forms to ODK Collect and submit data from ODK
Collect to ODK Aggregate.
• Data Viewer: able to log onto the ODK Aggregate website, filter, view, and export
submissions.
• Form Manager: all the capabilities of a Data Viewer plus the abilities to upload a
form definition, delete a form and its data, and upload submissions manually through
the ODK Aggregate website.
• Site Administrator: all the capabilities of a Form Manager plus the ability to add
users, set passwords, and grant these capabilities to other users.
You can also download a .csv template file with all the credentials and upload it to make
changes in bulk.
Remember to click Save Changes to make these changes take effect. You can also edit the
privileges for current users.

25.3.2 Preferences

In the Preferences sub-tab under Site Admin tab, you can manage:
• Google API credentials: These credentials are used when publishing into Google
services. For details on this, see Aggregate OAuth2 info.
• Enketo credentials: These credentials are used for Enketo webforms integration. To
link Enketo with Aggregate, see this.

510 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.4. Getting Data Out of Aggregate

• Aggregate features: These settings affect the operations of the server.


– Skip malformed submissions - check this to ignore corrupted submissions.

25.4 Getting Data Out of Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

ODK Aggregate supports three primary mechanisms for data transfer:


• Exporting: one time snapshot
• Publishing: continuous streaming of submissions
• APIs: programmatic access to the data
Since ODK supports complex data structures such as question grouping, repeating questions,
and multimedia, compromises have been made for each mechanism in regards to these data
structures. This document explains each mechanism and what each supports.

25.4.1 Exporting

The easiest way to get data from Aggregate is by using its ‘Export’ feature. Export allows
the user to manually export all of the data (or filtered data) at any time into one of the
following formats:

CSV (comma separated values)

CSV files are a text only, tabular representation of the data. Multimedia files are represented
by including standard web links to the files. Repeats are also represented with links to the
underlying data. Grouping information is not preserved. Metadata is only preserved if a
filter is created with the metadata.
To download CSV files of forms with repeats, consider using ODK Briefcase instead of ODK
Aggregate’s export functionality. Instead of repeats that are represented with links to the
underlying data, ODK Briefcase will export a set of CSV files, one for each repeating group.
ODK Briefcase will also export any multimedia as files (e.g., pictures will get exported as
JPEGs). The only metadata that is preserved is the submission date in the CSV is preserved,
but the XML files that ODK Briefcase downloads has all form metadata.

Note: To import CSVs into Excel, you cannot download and open in one step; nor can you
double-click on the CSV. You must open Excel and choose Import. If you are asked, the file

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 511
Chapter 25. Using ODK Aggregate

origin or encoding is UTF-8.

JSON

JSON is a text only representation of the data in a key:value format. Multimedia files are
represented by including standard web links to the files. Repeating data is preserved, but
grouping information not related to repeats is not. Metadata is only preserved if a filter is
created with the metadata.

KML (Keyhole Markup Language)

KML is a text only representation of the data similar to XML, but used for mapping appli-
cations like Google Earth. Multimedia files are represented by including standard web links
to the files hosted on the server. Pictures will appear embedded in popup windows (when
pushpins are clicked) in programs that render .kml files. Repeats and grouping information
is not preserved. Metadata is only preserved if a filter is created with the metadata.

Export Data Summary

Format Groups Repeats Multimedia Metadata


CSV(Aggregate) not pre- links to links to preservable
served
CSV(Briefcase) not pre- split into separate exported as only submission
served CSVs files date
JSON not pre- preserved links to preservable
served
KML not pre- not preserved links to preservable
served

25.4.2 Publishing

Aggregate provides mechanism for either bulk publishing data to another service, or for
streaming incoming data to a service as it is received, or both.

Warning: Under certain failure conditions, the downstream service can receive multiple
copies of a given submission. This is known, expected, behavior.

512 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.4. Getting Data Out of Aggregate

Tip:
• Duplicates typically occur if the downstream service is slow to respond or acknowledge
a request.
• It is your responsibility to detect and eliminate these duplicates should they occur
(they will always have exactly the same information in all fields).

Note:
• Publishing attempts happen at most every 15 minutes. If there are pending submissions
to publish, there will be attempts at most every 30 seconds until there are no pending
submissions.
• If ODK Aggregate aborts its publishing attempt before it gets an acknowledgment, it
will re-send the submission a short time later. If the downstream server successfully
processed the first request, the re-send of that same submission can cause a duplicate
record of it to appear in the downstream system. The instance ID of the submission
will appear as the metainstanceid column in Google Sheets and as the meta-instance-id
column in Google Fusion tables.
• When the downstream server fails to respond or responds with an error code, ODK
Aggregate first delays a re-send for 60 seconds, and, if that also fails, it then backs off
its publishing attempts, and will re-send at either 7.5-minute or 15-minute intervals
until the downstream service successfully responds, after which ODK Aggregate will
resume its normal publishing behavior.

Aggregate currently supports publishing data to the following services or in the following
formats:

Google Spreadsheets

Spreadsheets is Google’s cloud-hosted spreadsheet solution. Multimedia files are represented


by including standard web links to the files. Repeats are also represented with links to the
underlying data. All metadata is preserved. Spreadsheets has cell limits above which errors
will be reported. Spreadsheets also has an API that can be used to export/publish data.

Warning: Non-repeating grouping information is not preserved with Google Sheets.


Use globally unique names throughout your form or data might not transfer correctly to
Google Sheets.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 513
Chapter 25. Using ODK Aggregate

OAuth2 Service Account Required


Publishing data to Google Spreadsheets requires an oauth2-service.

JSON Server

JSON preserves grouping and repeat structures. The user can choose to let multimedia
files be represented as web links or embedded as base64 encoded strings. All metadata is
preserved.

Publish Data Summary

Service Groups Repeats Multimedia Meta-


data
Google Spread- not pre- links to links to pre-
sheets served served
JSON Server preserved pre- links to or embedded as pre-
served base64 served

25.4.3 APIs

ODK Aggregate has public APIs defined for sending data to and from its various components.
This section gives references to those API implementations that can be used for connecting
new applications to the ODK ecosystem.

Briefcase CLI

ODK Briefcase includes a CLI (Command Line Interface) to automate downloading forms
from ODK Aggregate (or ODK Collect) and exporting the forms to an Excel-compatible
format like CSV. For more details, see Working with command line on Briefcase.

Briefcase-Aggregate API

ODK Briefcase uses an API that external applications can use to pull all data from and push
data to ODK Aggregate.
Interfaces used during pull actions are:
• OpenRosa Form Discovery API

514 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.4. Getting Data Out of Aggregate

• download forms and media files using URLs form discovery


• view/submissionList to obtain a chunk of submission keys
• view/downloadSubmission to download an individual submission
Interfaces used during push actions are:
• formUpload to upload a form and its media files to ODK Aggregate
• view/submissionList to obtain a chunk of submission keys
• OpenRosa Form Submission/Overwrite API (with extensions)
For more details, see Briefcase Aggregate API.

OpenRosa API

Collect and Aggregate communicate using a standard set of API calls defined in the Open-
Rosa specification, which can also be used by alternative clients.

Direct database connection

Warning: This is an extremely dangerous way to access data from Aggregate because
table structure can and does change between versions. Moreover, changing any of this
data could corrupt your Aggregate install.

If you are running on a Tomcat server, you have access to the underlying MySQL or Post-
greSQL tables. The structure of those tables are documented at Aggregate Database Struc-
ture.

25.4.4 Accessing Media

Many of the export and publishing options provide a URL to the media (image, audio or
video) without providing the content itself. To enable the viewing (following) of this link
without requiring a log-in:
• Go to the Permissions sub-tab under the Site Admin tab.
• Check the checkbox for: Allow anonymous retrieval of images, audio and video data
(needed for GoogleEarth balloon displays).
• Click the Save Changes button.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 515
Chapter 25. Using ODK Aggregate

This allows anyone to view the media files on your server. Even though you are granting
anyone access to this information, it is still quite secure because the users would need to
have a valid URL.

25.5 Visualizing Geographic Data

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

This guide helps the users to visualize the collected geodata uploaded on ODK Aggregate
server using Google Earth.

Prerequisites

1. Make sure you have set up your ODK Aggregate server.


2. You should know how ODK Collect works.
3. You should be familiar with form designers like ODK Build, XLSForm to create your
location based forms and upload it to ODK Aggregate server.

25.5.1 Google Earth

Google Earth is a virtual globe that accesses satellite and aerial imagery, and other geographic
data over the internet to represent the Earth as a three-dimensional globe
Follow these steps to view your data using Google Earth:
1. Login to your ODK Aggregate server.
2. In the Submissions tab, under Filter Submissions, select the form you want to use and
click on Export

516 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.5. Visualizing Geographic Data

3. Choose the type as KML file and click on Export.

4. You don’t need to change the default options, but you can select the title according to
your choice. Click on Export
5. You will be redirected to Export Submissions page where you can download your kml
file.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 517
Chapter 25. Using ODK Aggregate

6. After downloading go to Google Earth website or you can download it from here. Wait
for a while as Google Earth takes time to load.

7. Click on and to enable KML import click on Settings.

518 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.5. Visualizing Geographic Data

8. In the Settings window, enable KML file import and click on SAVE.

9. Click on IMPORT KML FILE and import the downloaded kml file.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 519
Chapter 25. Using ODK Aggregate

10. Now you will be able to see your data in an organized manner on Google Earth.

Tip:
• On Google Earth, you can choose your map style, add additional points, lines and
polygons to add more information for the enhancement of map. You can also try out
this tutorial on how to annotate Google Earth.

520 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
25.6. Getting Help in Aggregate

25.6 Getting Help in Aggregate

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Aggregate provides three kinds of help accessible by pressing one of three buttons in the
upper righthand corner.
The red question mark will give you instructions for the tab you are currently viewing. When
you click the button, a help panel will appear at the bottom of the screen. To hide the help
panel, simply click the red question mark again.

The green book will give you the most comprehensive help. When you click the button, a
popup will appear providing detailed information as well as video instructions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 521
Chapter 25. Using ODK Aggregate

The blue balloon increases the amount of detail that appears describing the button’s func-
tionality when you hover over most buttons.

522 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYSIX

TIPS AND BEST PRACTICES

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

26.1 Aggregate Limitations

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

This is a listing of known limitations and potential ”gotchas” users of Aggregate may en-
counter.

26.1.1 Media held in memory

When a form submission is uploaded, and when blank forms are downloaded, all the associ-
ated media files are held in memory at the same time, twice. For forms with a lot of media
files, this can consume a lot of memory.
It is not absolutely critical to serialize form downloads, but you should probably manage
how many form download requests are being handled concurrently, in order to avoid memory
problems.

26.1.2 Uploading blank forms with media exceeding 10MB

Adding blank forms through the ODK Aggregate website is limited to an overall form and
media size of 10MB. Beyond that, you have to perform multiple uploads of the form definition
file with different subsets of the media files in order to fully upload the blank form and its
media attachments.
An easier solution is to use ODK Briefcase.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 523
Chapter 26. Tips and Best Practices

26.1.3 Issues with older versions of Aggregate

Aggregate < 1.4.8 used deprecated technology

Aggregate 1.4.7 and earlier use a deprecated backend technology. Google may terminate
support for that at any time with little warning. You should consider upgrading.

Aggregate 1.4.15 changed sync protocol

Aggregate 1.4.15 fixed the ODK-X rev 210 sync protocol. Prior to this, user permissions
were incorrectly being computed and filtered. This prevented resetting the server with new
content from the device (but syncing with existing content worked fine). The rev 210 sync
protocol is incompatible with anything prior to rev 210.

Basic Auth broken prior to Aggregate 1.4.14

OpenRosa servers are required to implement at least one authentication protocol as outlined
in RFC2617.
• a subset of RFC2617 Digest Authentication
• Basic Authentication.
Aggregate v1.4.14 added an SHA-1 library so that Basic Auth is possible. Prior to this,
Basic Auth was not possible.

Note: Basic Auth is not exposed in the setup wizard. Additionally, it requires that default
passwords be changed.

524 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYSEVEN

GOOGLE APP ENGINE SUPPORT (LEGACY)

Warning: Aggregate is no longer actively developed. Please use ODK Central instead.

Warning: In February 2019, ODK Aggregate v2.x was released with support for Google
App Engine removed. This page gathers all the information previously available about
Google App Engine for Aggregate v1.x. See why we are removing App Engine support
for more information.

27.1 Planning Your Aggregate Deployment

The recommended method to deploy Aggregate v1.x is using Google App Engine or the
ODK Aggregate VM . Try those first before attempting other methods.

27.1.1 Internet access

Google App Engine requires internet access. If you don’t have consistent internet access,
ODK Briefcase may be more appropriate.

27.1.2 Availability

Google App Engine provides highly available servers and data storage.

27.1.3 Dataset size

Google App Engine can store a virtually unlimited amount of data — well in excess of a
million submissions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 525
Chapter 27. Google App Engine Support (Legacy)

However, in deployments with data sets exceeding 7,000 submissions, the data export feature
will stop working. To correct this, you will need to increase server size.
On Google App Engine, a larger instance will incur higher billing costs. Additionally, for
datasets of over 100,000 records, it is likely that performance will be better when using
MySQL or PostgreSQL, rather than Google App Engine’s data store. You also have more op-
timization opportunities when running your own database servers than are available through
Google’s cloud services.

Note: Individual text database fields are capped at a length of 255 by default for perfor-
mance reasons. If you intend to collect text data longer than 255 characters (including using
types geotrace, geoshape or select multiple), your forms should specify database field lengths
greater than 255.

27.1.4 Data locality and security

Google App Engine servers may be located anywhere in the world.


Depending on the sensitivity of the data and specific storage rule, regulations, or restrictions
of your country or organization, the server infrastructure may not have all necessary locality
guarantees or security precautions.
In some circumstances, you might be able to use encrypted forms to achieve compliance.
You should research and comply with applicable laws and regulations before storing data on
Google App Engine.
See also:
Google Cloud Services Terms of Service.

27.1.5 Billing

For identity verification purposes, Google requires a credit card or banking details to use
the Google Cloud Platform that Google App Engine runs on. Accounts that meet this
requirement receive a recurring $200 monthly credit per billing account.
Independent of Cloud Platform credits, App Engine allows a certain amount of free activity.
These free quotas reset every 24 hours and are high enough to enable free use of ODK
Aggregate during evaluation and small pilot studies.
You may be able to run a full deployment within these activity thresholds provided you:
• collect fewer than 2000 responses
• access the site a limited number of times a day

526 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
27.1. Planning Your Aggregate Deployment

• can be flexible about when you upload and access data


Deployments with more activity that do not wish to wait 24 hours for quotas to reset can
enable billing on their App Engine project.
Once billing is enabled, ODK Aggregate will start using the monthly credit that comes from
the Cloud Platform. Once those credits are finished, the credit card or bank on file will then
be used. Billing account owners can set spending limits to manage application costs.
Most ODK deployments will not surpass the $200/month credit and non-profits using more
than that can apply for more credits through Google for Nonprofits.

27.1.6 Cost effectiveness

For most users, Google App Engine will be the easiest and most cost-effective option.
Two examples illustrate the cost-effectiveness of Google App Engine:
• The fee to run the ODK Aggregate Demo Server is near the minimum weekly charge,
costing a few dollars a week.
• A 6000 hour study in Mumbai that ran from 01 September 2011 through 29 Febru-
ary 2012 also incurred the minimum charge of $2.10/week for mid-November onward
(Google did not begin billing until mid November 2011).
You can enable billing on an as-needed weekly basis. You will incur no charges at all if you
disable billing (for example, between data gathering campaigns, while you are developing
the forms for the next campaign). When disabled, access is restricted to the free daily usage
limit.

27.1.7 Minimizing fees

Hint: In the Preferences sub-tab under Site Admin tab, you can Disable faster background
actions to reduce App Engine quota usage.

On App Engine, the major driver of cost is Datastore Reads. These add up quickly:
• Viewing a page of form submissions incurs at least one Read for each submission.
• Each multiple-choice question in a form incurs an additional Read on every displayed
submission.
• An additional read is incurred for every 200 questions in your survey.
• Each image incurs at least 10 reads.
• The default view shows 100 submissions.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 527
Chapter 27. Google App Engine Support (Legacy)

• The form submissions display refreshes every six seconds.


For example, if your survey has 500 questions (q), with a repeat group containing an addi-
tional 300 questions, the typical survey has 4 filled-in repeats (rpt), and 100 submissions (s)
are shown on each page load (pl), then the cost to display the Submissions tab is a minimum
of 1100 Reads (R) with each refresh of the Submissions tab.
100s/pl × (500q/s × ⌊1R/200q⌋ + 4rpt/s × 300q/rpt × ⌊1R/200q⌋) = 1100 R/pl
At this rate, the free quota would be exceeded within 5 minutes!
And this hypothetical survey did not contain any select-one or select-multiple questions, or
any audio, video or image captures, all of which would require more Reads.
Therefore, to reduce datastore reads:
• restrict access to the Aggregate website
• do not keep the browser window open on the submissions tab
• export or publish your data, and do your analysis in a different tool
• use ODK Briefcase instead of Aggregate to generate CSV files
It is generally more efficient to use Briefcase to generate CSV files than to use Aggregate,
as Briefcase will use the locally cached data to generate the CSV files.
With larger datasets, there are two modes of operation:
• Aggregate retains the full dataset.
In this mode, it is slightly more efficient to Pull data to your local computer then
immediately Push it back up. This sets some internal tracking logic within Briefcase
so that the next Pull is somewhat more efficient, as the Push only verifies that what
you have locally matches the content on Aggregate, rather than re-uploading all of it.
• Aggregate retains only a portion of the dataset.
In this mode, you periodically purge older data collection records and never Push data
up to Aggregate, as that would restore the purged data.

27.2 Installing Aggregate

See Installing Aggregate on Google App Engine.

27.3 Backing up Aggregate

You can export and import Datastore entities using the managed export and import service.
See ODK Aggregate data wrangling for App Engine for more detail.

528 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
27.4. Tips and Best Practices

27.4 Tips and Best Practices

27.4.1 Aggregate Limitations

Pushing Data to Aggregate

If Aggregate is installed on Google App Engine, using the default datastore as described
in our documentation, a combination of request time limits and datastore implementation
create the following issues.
Simultaneous push requests will block each other and may time out
Within ODK Aggregate, there is a global mutex (TaskLock across all server instances, me-
diated by the datastore layer) in the server when inserting submissions. Having multiple
push requests occurring simultaneously will cause them to block on the mutex, chewing up
their 60-second request limit, as they get processed in single file no matter how many server
instances are spun up.
The solution to this is: Serialize your push requests.
Time limit may be exceeded on low-bandwidth connections
The 60-second request limit can be very commonly exceeded over low-bandwidth connections,
and even text-only submissions can be impacted on satellite connections. That is why ODK
Collect splits submissions into multiple 10MB submission requests. The timer starts upon
receipt of the first byte, so a slow connection can account for a sizeable portion of those 60
seconds. The same applies for sending a response. The processing on the server is generally
negligible in relation to the transmission times.

Note:
• The above two limitations, the global mutex and the in-memory copies/full-packet-
assembly, are a result of implementing on top of App Engine and its Datastore.
• A server that used database transactions and that used streaming servlet 3.0 function-
ality would have less trouble with concurrent requests.

Media held in memory

When a form submission is uploaded, and when blank forms are downloaded, all the associ-
ated media files are held in memory at the same time, twice. For forms with a lot of media
files, this can consume a lot of memory.
The previous section already suggested serializing form submission uploads. This is not
absolutely critical for form downloads, but you should probably manage how many form

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 529
Chapter 27. Google App Engine Support (Legacy)

download requests are being handled concurrently, in order to avoid memory problems.

27.4.2 Reducing Data Corruption and Boosting Performance

See Reducing Data Corruption and Boosting Performance on Google App Engine.

530 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYEIGHT

CONTRIBUTING TO ODK DOCS

28.1 Docs Contributor Technical Guide

This document explains how to set up your computer and work locally as an ODK Docs
contributor. Local set up includes installing some software, and working locally involves:
• writing documentation text or code in a code editor
• using the Terminal (the ”Shell” or ”Command Line”)
We encourage all potential contributors to try to work locally, following this guide.

28.1.1 Before you begin

Learn a little about ODK

Read about the project and the community at ODK’s website.


Get started with the docs by going to the ODK Docs GitHub README.

Set up collaboration accounts

ODK is a collaborative community. Before diving in as a contributor, set up accounts on


our three main collaboration platforms, GitHub, the ODK Developer Slack, and the ODK
Forum

Tip: As you are setting up your accounts, keep in mind that it is very helpful (but not
required) to use the same (or similar) username on GitHub, the ODK Developer Slack, and
the ODK Forum.
This makes it easy for other people to keep track of conversations which sometimes span
multiple online platforms.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 531
Chapter 28. Contributing to ODK Docs

If you are willing and able to do so, a profile picture in each place is also very helpful. (But
it is okay if you are unable or uncomfortable adding a picture.)

1. Set up a GitHub account.


GitHub is a popular code storage and collaboration platform. You will need a GitHub
account to contribute to ODK documentation, or any other ODK projects.
• ODK on GitHub
• ODK Docs on GitHub
2. Join the ODK Developer Slack.
Slack is a popular chat platform. The ODK contributor community uses Slack to
discuss development, plan work, and generally keep in touch. If you have a question
about how to contribute to ODK Docs, or any other ODK project, the ODK Slack is
the best place to ask it.
Conversations related to documentation are held in the #docs-code channel. You may
also want to check in with #general and #random.
(a) Get an automated invitation from http://slack.getodk.org
(b) Check your email for the invitation.
(c) Follow the link in your email and set up your account.
3. Join the ODK Forum
The ODK Forum is the main place for support questions and conversations that affect
the whole ODK community (users and other stake holders, as well as contributors).
If you have a question about how to use any ODK software, or want to get connected
with the larger ODK community, the forum is the best venue for that.

Tip: The forum has a search feature, and a long history of archived support posts.
When writing new documentation about an existing feature, old forum posts are an
excellent source for figuring out what people need to know: If someone has asked a
question about it, it should probably be in the documentation.

Should I ask in the Forum, the Slack, or a GitHub issue?


The ODK community talks a lot, in a lot of places. Sometimes it’s hard to know where to
ask a question.
Contribution-related questions and problems should be asked in Slack. This
includes things like:
• How do I set up my local editing environment?

532 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

• How do I use git?


• I’m having a merge conflict.
• I got an error at the terminal which I don’t understand.
• How do I add a picture to a document?
• What issue should I work on?
Work-specific questions and discussion should take place on the GitHub issue
defining the work. This includes things like:
• I’m writing a piece of content, but I’m not sure where it should be organized.
• I’d like to work on this feature, but I don’t know how to implement it.
• Here’s my idea for solving this problem. Is that a good idea?
• I’m going to be working on this for the next few days. No one else should also work
on it at the same time.
• I said I was working on this, but I didn’t finish and I’m no longer working on it.
User-related questions and problems should be asked in the Forum. (You should
use the search feature first, since someone else may have already asked the same question.)
This includes things like:
• How do I install an ODK application?
• How do I create a form?
• How do I add a specific feature to a form?
• My ODK application crashed.

But don’t worry about posting a question in the wrong place.

It is better to ask a question in the ”wrong” venue than to not ask the question at all. Many
of the same people are present in all three places, and we will help you wherever you happen
to show up.

28.1.2 Initial Setup

Note: We generally recommend starting with the Docker platform for editing docs unless
you already have a Sphinx environment set up. Local tools and workflows presented in this
guide are what the authors feel would be easiest for newcomers and those unfamiliar with
open source.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 533
Chapter 28. Contributing to ODK Docs

However, developer and authoring tools have a lot of options and alternatives. You should
feel free to use your preferred tools.

Before you begin working the first time you will need to install a few tools on your computer.
You should only need to do this one time on any computer.
1. Find and open a terminal or command line.
Windows
Mac
Linux

Windows versions prior to Windows 10

Use Windows PowerShell. (Not the DOS Prompt.)


We recommend using the Windows PowerShell ISE.
During initial setup (this section of the guide) you will need to Run as Administrator.
Throughout the rest of the instructions in this guide, follow the instructions labeled
PowerShell or Windows.

Windows 10

In Windows 10, you have a choice:


• Use the Powershell (as described above)
• Use the Windows Subsystem for Linux.
If you decide to use the Powershell, follow the Powershell or Windows instructions
throughout the contributor guides.
If you decide to use the Linux subsystem, follow the Bash or Windows instructions
throughout the contributor guide.

Note: Computers with the Windows 10 Home operating system are in-
capable of installing some of the tools necessary to edit the docs. Other
Windows operating systems, such as Windows 10 Enterprise or Pro, can be
used to edit the docs.

Use the Terminal app, or another Bash-like shell.

534 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

If you’ve never used it before, the Terminal is probably in the Other directory in your
App collection.
Follow the Bash or Mac instructions throughout the contributor guide.

Optional: Install Homebrew


Homebrew is a package manager for Mac OS. It makes it easier to install other apps
and tools from the command line.
Follow the installation instructions.

Use a Bash-like shell of your choosing, and follow the Bash or Linux instructions
throughout the contributor guide.
You will also need to be familiar with the relevant package manager for your system.
2. Install git.
Git is a version control system. It helps us keep track of changes to the documentation.
(Similar to the undo history in a document editing program.)
Linux
Mac
Windows
Use your distribution’s package management system to install git on Linux.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 535
Chapter 28. Contributing to ODK Docs

Option 1: Download an installer

(a) Download the git installer for Mac.


(b) Open the installer package.
(c) Follow the prompts.
(d) Accept any default settings.

Option 2: Use Homebrew to install git

$ brew install git

(a) Download the git installer for Windows.


(b) Open the installer package.
(c) Follow the prompts.
(d) Accept any default settings.
3. Install Git LFS
Git Large File Storage (Git LFS) is a tool that helps us manage images, videos, and
other files which are neither text nor code.
Linux
Mac
Windows
Use your distribution’s package management system to install Git LFS on Linux.
After initial installation by the package manager, complete the install by running:

$ git lfs install

(a) Download Git LFS from the Git LFS website.


(b) Open the downloaded installer.
(c) Follow the prompts.
(d) Accept any default settings.
(e) Open the Terminal and add LFS to git:

$ git lfs install

536 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

Option 2: Use Homebrew to install Git LFS.

$ brew install git-lfs


$ git lfs install

(a) Download Git LFS from the Git LFS website.


(b) Open the downloaded installer.
(c) Follow the prompts.
(d) Accept any default settings.
(e) Open Powershell and add LFS to git:

> git lfs install

4. Install Python 3
Python is a programming language.
Most of the ODK Docs tools are written in Python, so you need it installed on your
computer in order to use those tools. (Don’t worry. You don’t need to know how to
program in Python.)
We require Python 3, version 3.6 or later.
Linux
Mac
Windows
Use your distribution’s package management system to install Python 3.6+ on Linux.
(For more help, see Installing Python on Linux.)

Tip: Mac OS includes a legacy (outdated) version of Python. It’s best to just ignore
it.

Option 1: Use the Python Installer for Mac

(a) Download the latest Python installer for Mac.

64-bit or 32-bit?
Python provides 64-bit and 32-bit installers. You probably need the 64-bit in-
staller.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 537
Chapter 28. Contributing to ODK Docs

If you are running a relatively recent Mac OS update (Mountain Lion or later —
any Mac from the last several years) the 64-bit installer is for you.
If you have an older Mac, and are unsure if it can run a 64-bit installer, check the
processor details in � -> About This Mac.

(b) Open the Installer.


(c) Follow the prompts.
(d) Accept the default settings.
(e) Open the Terminal to see if Python installed properly.

$ python3 --version
Python 3.7.0

The output from python3 --version might be a little different, but it should be
higher than 3.6.
If you get an error here, something went wrong. Try running the installer again.
If the problem persists, and you can’t debug it yourself, asks us about it on ODK
Slack.

Option 2: Use Homebrew to install Python 3.6+

$ brew install python


.
.
.
$ python3 --version
Python 3.7.0

The output from python3 --version might be a little different, but it should be
higher than 3.6.
If you get an error here, something went wrong. Try running brew install python
again. If the problem persists, and you can’t debug it yourself, asks us about it on
ODK Slack.
(a) Go to the Python Releases for Windows page.
(b) Under the latest numbered release for Python 3, find and download the Windows
x86-64 web-based installer (for a 64-bit system) or the Windows x86
web-based installer (for a 32-bit system).

64-bit or 32-bit?

538 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

Well over 90% of computers running Windows are 64-bit. So you probably need
the 64-bit version.
If you are running a very old or low-powered computer, and you are unsure if
it is 64-bit or 32-bit, you can use this guide from HP (which will work for other
computer brands) to find that information.

(c) Open the downloaded installer.


(d) Follow the prompts.
(e) Accept all default settings.
(f) Open Powershell and make sure the installation completed.

> python --version


Python 3.7.0

The output from python --version might be a little different, but it should be
whatever numbered version you downloaded.
If you get an error here, something went wrong. Try running the installer again.
You may also have to add Python to your Windows search path. You can do
this by going to Advanced System Settings -> Environmental Variables -> Edit
System Variables, then adding the path to the directory containing Python. If
the problem persists, and you can’t debug it yourself, asks us about it on ODK
Slack.
5. Set up your working directory
In whatever directory (folder) on your computer where you organize projects, create a
new directory for ODK, and then navigate to that directory. (We recommend calling
this directory odk, and the rest of the guide will assume that’s what you called it.)
Bash
PowerShell

$ mkdir odk
$ cd odk
/odk/ $

> mkdir odk


> cd odk
/odk/ >

For the rest of this guide, we assume you are in the /odk/ directory, or a subdirectory
of it.
6. Set up a virtual environment

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 539
Chapter 28. Contributing to ODK Docs

A virtual environment is a Python construct that lets you download and install tools
for a specific project without installing them for your entire computer.
(a) Create the virtual environment.
Bash
PowerShell

/odk/ $ python3 -m venv odkenv

/odk/ > python -m venv odkenv

(b) Activate the virtual environment.


Bash
PowerShell

/odk/ $ source odkenv/bin/activate


(odkenv) /odk/ $

/odk/ > source odkenv/bin/activate


(odkenv) /odk/ >

The (odkenv) before the prompt shows that the virtual environment is active.
You will need to have this active any time you are working on the docs.
If the file cannot be found, your activate file may be located under od-
kenv/scripts/activate.
Later, to deactivate the virtual environment:
Bash
PowerShell

(odkenv) /odk/ $ deactivate


/odk/ $

(odkenv) /odk/ > deactivate


/odk/ >

7. Fork the ODK Docs repository to your own GitHub account.


A repository (repo) is a store of all the code and text for a project. The ODK Docs
repo is kept at GitHub.
On GitHub, a fork is a copy of a repo, cloned from one user to another. In order to
work on ODK Docs, you will create your own fork.

540 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

(a) Go to the ODK Docs repo on GitHub.


(b) Use the Fork button (top right) to create your own copy.
(c) After the process completes, you’ll be looking at your own fork on GitHub.
8. Clone down your copy to your local computer
(a) From your own fork of the repo on GitHub, select the Clone or download button.
(b) Copy the URI from the text box that opens. It will be something like: https://
github.com/your-gh-username/docs.git
(c) Use your terminal to clone the repository.
You should already be in the odk directory, with the virtual environment active.
Bash
Powershell

(odkenv) /odk/ $ git clone https://github.com/your-github-username/docs.


,→git

.
.
.
(odkenv) /odk/ $ cd docs
(odkenv) /odk/docs/ $

(odkenv) /odk/ > git clone https://github.com/your-github-username/docs.


,→git

.
.
.
(odkenv) /odk/ > cd docs
(odkenv) /odk/docs/ >

Warning: Some of the git commands produce meaningless errors in Pow-


erShell. If you get an error when using git, but everything seems to work
otherwise, ignore the error.

Note: This will cause your computer to download the entire ODK Docs reposi-
tory, including a large number of images. It will take several minutes to complete.

Your local directory

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 541
Chapter 28. Contributing to ODK Docs

If you followed the instructions, you should now have the following directory
structure:
• odk
– docs
– odkenv
The odkenv directory stores your virtual environment, and you should not need
to open it or directly view its content. Just ignore it.
The docs directory is your copy of the ODK Docs repo. You will do most of your
work in this directory.
If you need to download or create additional files which are not actually a part of
the ODK Docs repository, keep them out of the docs directory.
You can use the main odk directory for any other files you need to work on. (For
example, you may want to create a directory called odk/forms to hold XLSForm
and XForm files.)

9. Set the upstream remote


In git, a remote is a copy of a repo somewhere else. From your local computer’s point
of view, your online copy at GitHub is a remote.
When you cloned down a repo, your local copy gives your GitHub copy the name
origin.
You also need to give the primary ODK Docs repo a name, and our convention is to
name it upstream.
Bash
PowerShell

(odkenv) /odk/docs/ $ git remote add upstream https://github.com/getodk/


,→docs.git

(odkenv) /odk/docs/ $ git remote -v


origin https://github.com/your-github-username/docs.git (fetch)
origin https://github.com/your-github-username/docs.git (push)
upstream https://github.com/getodk/docs.git (fetch)
upstream https://github.com/getodk/docs.git (push)

(odkenv) /odk/docs/ > git remote add upstream https://github.com/getodk/


,→docs.git

(odkenv) /odk/docs/ > git remote -v


origin https://github.com/your-github-username/docs.git (fetch)
origin https://github.com/your-github-username/docs.git (push)

542 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

upstream https://github.com/getodk/docs.git (fetch)


upstream https://github.com/getodk/docs.git (push)

If everything went right, you should see output similar to what is shown above.
10. Install Python tools with pip
Pip is a package management tool that comes with Python. We use it to download and
install our documentation tools. These Python tools are listed in requirements.txt.
Bash
PowerShell

(odkenv) /odk/docs/ $ pip install --upgrade pip


(odkenv) /odk/docs/ $ pip install -r requirements.txt

(odkenv) /odk/docs/ > pip install --upgrade pip


(odkenv) /odk/docs/ > pip install -r requirements.txt

The first command upgrades pip itself to the latest version. Then second checks
requirements.txt and installs everything listed in it. This will take several moments.

Note: If you are ever running one of the build commands shown below and it
fails with a message that includes ModuleNotFoundError, there might be changes to
requirements.txt since you originally ran pip install -r requirement.txt. Run
the installation again and then retry your build.

11. Choose a text/code editor


The documentation source files are written in a plain text format called reStructured-
Text. This means special formatting (bullets, headers, bold text) is represented by
visible characters, not hidden behind a graphical display. When working on a docu-
mentation file, you see and write something that looks like:

#. Choose a text/code editor

The documentation source files


are written in a plain text format called `reStructuredText`_.

.. _reStructuredText: http://docutils.sourceforge.net/docs/user/rst/
,→ quickref.html

You cannot write and edit these files in a typical document preparation program like
MS Word or Google Docs. Instead, you need a coding editor.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 543
Chapter 28. Contributing to ODK Docs

There are a lot of editors, and people who use them often have very strong opinions
about them. You are free to choose any editor you like.
If you’ve never used an editor before, you might want to start with one of the easier
and more popular ones:
• Atom
• Sublime
• VS Code
• Notepad++ (Windows only)
Most of these have plugins that will make writing reStructuredText easier by color-
coding the markup.
This completes the setup of your local working environment. Take a break before diving into
how you actually work.

28.1.3 Working on the docs

1. Find an issue to work on.


Work on ODK Docs is planned using the GitHub repository’s issue tracker.
(a) Browse the issue tracker and find one you may want to work on.
(b) Make sure you understand the goal of the project. If the goal isn’t clear, ask. If
there is anything in the issue that doesn’t make sense, ask about it. Feel free to
make suggestions about how something could be accomplished.
(c) If you decide to work on an issue, assign yourself to it by writing @getodk-bot
claim in a comment.
(d) If the issue requires a novel or creative solution not defined in the issue already
(we’ve stated a problem and you think you know a way to fix it) write a comment
describing your plan. It is a good idea to get feedback on an idea before working
on it. Often, other contributors can provide additional context about why a
particular solution may or may not work.

Your first issue


The very first issue you should work on as a new ODK Docs contributor is Issue 96 —
Line Edits. The issue is very simple:
(a) Find a typo.
(b) Fix the typo.

544 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

This will help you get used to working with the documentation tools, and helps us get
rid of the inevitable errors that creep in to our writing.

2. Make sure you are on the master branch


A branch is a named sequence of changes representing work on the repo. For example,
if you were going to work on Issue 96 — Line Edits, you would create a new branch
called line-edits to hold that work. When you were done, you would merge those
changes back to the main branch, which we call master.
The first time you clone the docs repo and start working, you will be on the master
branch.
Each time you come back to starting work on a new issue, make sure you are on the
master branch before continuing.
(a) Check the current branch with git branch. This will output a list of branches,
with a star next to the current one.
Bash
PowerShell

(odkenv) /odk/docs/ $ git branch


branch-name
branch-name
branch-name
* master
branch-name

(odkenv) /odk/docs/ > git branch


branch-name
branch-name
branch-name
* master
branch-name

(b) If you are not on master, switch to master with git checkout.
Bash
PowerShell

(odkenv) /odk/docs/ $ git checkout master


Switched to branch 'master'
Your branch is up to date with 'origin/master'.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 545
Chapter 28. Contributing to ODK Docs

(odkenv) /odk/docs/ > git checkout master


Switched to branch 'master'
Your branch is up to date with 'origin/master'.

3. Pull in changes from upstream


Other people are constantly making changes to the docs, so you need to keep your
local copy up to date.
Before you start working, use git pull to pull in the changes from the upstream
repository’s master branch. Then, just to be sure, you can use git status to make
sure everything is up to date.
Bash
PowerShell

(odkenv) /odk/docs/ $ git pull upstream master


(odkenv) /odk/docs/ $ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

(odkenv) /odk/docs/ > git pull upstream master


(odkenv) /odk/docs/ > git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Warning: Some git commands (including git pull and git checkout) send
error messages to PowerShell even when they work correctly. If everything seems
to be working, you can ignore these.

4. Create a new branch for your work.


Bash
PowerShell

(odkenv) /odk/docs/ $ git checkout -b branch-name


Switched to a new branch 'branch-name'

(odkenv) /odk/docs/ > git checkout -b branch-name


Switched to a new branch 'branch-name'

546 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

Branch names should be short, lowercase, and use hyphens as separators. They do not
need to carry a lot of information (like your name or the date).
Good branch names:
• getting-started-guide
• contributing
• fix-issue-13
Bad branch names:
• getting started guide
• Getting started guide
• Getting_started_guide
• writing-the-getting-started-guide-adammichaelwood-july-2017-draft
5. Work on the documentation
Finally, you can open an editor of your choice and work on the documentation.
The source files for documentation text are in these directories:
odk1-src Files for the pages at https://docs.getodk.org
shared-src Files for pages shared by both ODK1 and ODK-X docs. (This page and
the other contributor guide pages.)
If you’re going to write or edit documentation text, please read:
• Docs Markup and Syntax Guide
• Docs Style Guide
If you’re working on code or deployment, please read:
• Docs Developer Guide
6. Local checks
Once you have worked on the documentation, we want to make sure your contribution
will get accepted and published right away.
To ensure your changes will pass all the deployment tests, you should run the tests
locally first and correct any problems.
(a) Spell check
If you’ve been working on files in odk1-src or shared-src:
Bash
PowerShell

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 547
Chapter 28. Contributing to ODK Docs

(odkenv) /odk/docs/ $ make odk1-spell-check

(odkenv) /odk/docs/ > rm -r -fo tmp1-src


(odkenv) /odk/docs/ > rm -r -fo odk1-build
(odkenv) /odk/docs/ > Copy-Item odk1-src -Destination tmp1-src -Recurse
(odkenv) /odk/docs/ > Copy-Item shared-src -Destination tmp1-src -
,→Recurse

(odkenv) /odk/docs/ > sphinx-build -b spelling tmp1-src odk1-build/


,→spelling

(odkenv) /odk/docs/ > python util/check-spelling-output.py odk1-build

This will send some output to the terminal, which will include mentions of any
words not in the dictionary.
• If the flagged words are really misspellings, correct them.
• If the flagged words are not misspelled, and should be in the dictionary add
them to spelling_wordlist.txt.
• If the flagged words are not misspelled, but should not be in the dictionary
(for example, they are non-words that make sense on a single page for a
specific reason) add them at the top of the file in which they are being used,
before the title heading:

.. spelling::

abc
def
exe
functool

This Is The Page Title


======================

When adding new words to spelling_wordlist.txt or the top of a document


file, please keep the words in alphabetical order.
(b) Style check
7. Build and check
We use a Python tool called Sphinx to compile all the .rst files into a working website.
If you’ve been working on files in odk1-src or shared-src:
Bash
PowerShell

548 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

(odkenv) /odk/docs/ $ make odk1

(odkenv) /odk/docs/ > rm -r -fo tmp1-src


(odkenv) /odk/docs/ > rm -r -fo odk1-build
(odkenv) /odk/docs/ > Copy-Item odk1-src -Destination tmp1-src -Recurse
(odkenv) /odk/docs/ > Copy-Item shared-src -Destination tmp1-src -Recurse
(odkenv) /odk/docs/ > sphinx-build -b dirhtml tmp1-src odk1-build

This generates a lot of output. Near the end of the output you may see a statement
like:

build succeeded, 18 warnings.

Those warnings are problems with the text which you need to fix before submitting
your changes. Scroll up in the terminal to find each warning, so that you can address
it in the source files.
A Sphinx warning looks like this:

/path/to/file-name.rst:LINENUMBER: WARNING: warning message

short excerpt from the file

This tells you what file the problem is in, the approximate line number, and the nature
of the problem. Usually that is enough to fix it. If you can not figure out the meaning
of a particular warning, you can always ask about it on the ODK Slack.

Note: Because of a bug in Sphinx the line numbers in error and warning messages
will be off by about 15 lines (the length of rst_prolog in conf.py).

As you fix each warning, run the build again to see if it disappears from the output.

Note: The warning messages will refer to the file name using the temporary directory
path tmp1-src or tmpx-src. You need to correct the problems in the real source
directory (odk1-src, or shared-src).

When you just can’t fix the error…


If you’ve done your best and asked on the ODK Slack, and you still cannot correct
the warning, stop worrying about it and skip to the next step. When you submit your
changes on GitHub, include a note about the warning. Other contributors will help
solve the problem before merging.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 549
Chapter 28. Contributing to ODK Docs

Once you’ve corrected all the warnings that can be corrected…


8. Serve the documentation website locally and view it.
If you’ve been working on files in odk1-src or shared-src:
Bash
PowerShell

(odkenv) /odk/docs/ $ python -m http.server -d odk-build 8000


Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/)

(odkenv) /odk/docs/ > python -m http.server -d odk1-build 8000


Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/)

(a) Open your browser and go to http://localhost:8000.


(b) Read through your doc edits in the browser.
(c) Go back to the source files to correct any errors you find.
(d) Go to your terminal, and press CTRL C to shut down the local web server.
(e) Re-run the build and serve steps.
(f) Continue proofreading.
Once you are reasonably sure your changes are ready…
9. Commit your changes to your local repository.
A commit is snapshot of your working files in a particular state, along with a record
of all the changes that led up to that state. That snapshot is what you will submit to
the main repository.

Note: We explain how to do a commit at this step because you need to do it before
you can submit your changes. However, you don’t have to wait until you are done to
commit. You can commit as many times as you like while working.
This can be especially helpful if you are working on a complicated set of changes, over
several working sessions.

(a) Stage the files for commit with git add.


To stage all changes for commit:
Bash
PowerShell

550 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

(odkenv) /odk/docs/ $ git add -A

(odkenv) /odk/docs/ > git add -A

(b) Commit the staged files with git commit.


Bash
PowerShell

(odkenv) /odk/docs/ $ git commit -m "Write a commit message here."

(odkenv) /odk/docs/ > git commit -m "Write a commit message here."

Your commit message needs to be wrapped in quote marks. It should, in a


sentence or less, explain your work.
10. Push your committed changes to your GitHub repo with git push.
Bash
PowerShell

(odkenv) /odk/docs/ $ git push origin branch-name

(odkenv) /odk/docs/ > git push origin branch-name

Warning: The git push command produces meaningless errors in PowerShell.


If you get an error when using git push, but everything seems to work otherwise,
ignore the error.

Tip: You may be prompted to enter your GitHub username and password. When
entering your password, the cursor won’t move — it will look like you aren’t entering
anything, even though you are.
To avoid having to retype these every time, you can store your GitHub credentials
locally.

11. Issue a pull request from your GitHub repo to the main ODK Docs repo.
A pull request (or PR) is a request from you to the ODK Docs maintainers to pull in
your changes to the main repo.
(a) Go to the ODK Docs repo on GitHub. (Make sure you are logged in.)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 551
Chapter 28. Contributing to ODK Docs

(b) Find the message near the top of the page that mentions your recent pushed
branches. Select Compare & pull request to start a pull request.
(c) Follow GitHub’s instructions to start the pull request.
These details should fill-in automatically, but be sure to double-check them:
• Base fork should be the main repo (getodk/docs).
• base should be master.
• Your repo and working branch name should be listed beside them.
You will see either a green Able to be merged message or a message informing
that the branch can not be merged. You can proceed in either case. If the branch
cannot be merged, the maintainers will work with you to resolve the problem.
(d) Write a PR message explaining your work.
The PR message field includes a template to remind you of what to include. Fill
in the template and delete any sections which are not applicable.
A good PR message includes:
• The issue number you are working on. (Write closes #123 if the PR com-
pletes the work for the issue. If there’s still work to do, write addresses
#123.)
• A summary of what you did.
• Details of work that still needs to be done.
• Details of new work created or implied by this PR.
• Details of any unresolved errors or warnings, including details of what you
tried.
• Justification for any changes to requirements.txt.
• Details of any difficulties, questions, or concerns that came up while working
on this issue.
(e) Submit your pull request.
The maintainers and other contributors will review your PR as quickly as possible.
They may request changes to your work. If changes are needed:
(a) Don’t worry. Revision is a normal part of technical writing, and everyone (even
the project’s founders and leaders) has their work reviewed and are frequently
asked to revise it.
(b) Work on the files again locally. (Use git branch to make sure you are still in
the same working branch.)

552 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.1. Docs Contributor Technical Guide

(c) Stage and commit your changes locally again (git add -A; git commit -m
"Commit message").
(d) Push your commit (git push origin branch-name).
(e) Your new commits will automatically update the PR. Do not start a new PR.
Once everything has been approved, the changes will be merged in and will appear on
this website. At that point… congratulations! You are now a contributor to ODK.

28.1.4 The next time you work

We hope that contributing to ODK Docs is a rewarding experience and that you’ll want
to keep going. Each time you start work on a new issue the process is the same as outline
above.
Here are a few things to keep in mind when you start your next contribution.
1. Return to master with git checkout master.
New work is done on new branches which are started from master. So, before you start
a new branch, return to the master branch.
Bash
PowerShell

(odkenv) /odk/docs/ $ git checkout master

(odkenv) /odk/docs/ > git checkout master

2. Pull in changes with git pull upstream master.


You need to start your new work from the latest version of everyone else’s work.
Bash
PowerShell

(odkenv) /odk/docs/ $ git pull upstream master

(odkenv) /odk/docs/ > git pull upstream master

3. Update the master branch of your online GitHub repository.


Bash
PowerShell

(odkenv) /odk/docs/ $ git push origin master

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 553
Chapter 28. Contributing to ODK Docs

(odkenv) /odk/docs/ > git push origin master

4. Find a new issue to work on.


5. Start a new branch for your work with git checkout -b branch-name.

28.1.5 Keep improving

As you are getting comfortable with the contribution process, take a few minutes to read
our Tips for Making Good Contributions. You may also want to dig deeper into the Docs
Style Guide and the Docs Markup and Syntax Guide. (And if you are writing code, check
out the Docs Developer Guide.)
And don’t forget to join us on the ODK Slack.
ODK is a community, and we depend on each other’s work. Thank you for your contribution
to ODK Docs and your presence in this community.

28.2 Docs Markup and Syntax Guide

The ODK documentation is built using Sphinx, a static-site generator designed to create
structured, semantic, and internally consistent documentation. Source documents are writ-
ten in reStructuredText, a semantic, extensible markup syntax similar to Markdown.
• reStructuredText Primer — Introduction to reStructuredText
– reStructuredText Quick Reference
– reStructuredText 1-page cheat sheet
• Sphinx Markup — Detailed guide to Sphinx’s markup concepts and reStructuredText
extensions

Note: Sphinx and reStructuredText can be very flexible. For the sake of consistency and
maintainability, this guide is highly opinionated about how documentation source files are
organized and marked up.

28.2.1 Indentation

Indentation is meaningful in Sphinx and reStructuredText text. Usually, indenting a section


means that is ”belongs to” the line it is indented under. For example:

554 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

.. figure:: path-to-image.*

This is the caption of the figure. Notice that it is indented under the line␣
,→ defining the figure.

The rules for indentation are:


• Use spaces, not tabs.
• Generally, indent two spaces.
The exception to the two spaces rule is Ordered (numbered) lists, where indentation follows
the content of the list item.

1. This is a list item.

This is some additional content related to Item 1. Notice that it is indented␣


,→to the same column as the first line of content. In this case, that's three␣
,→(3) spaces.

.
.
.

10. The tenth item in a list.

This related content will be indented four spaces.

28.2.2 Documentation Files

Sphinx document files have the .rst extension. File names should be all lowercase and use
hyphens (not underscores or spaces) as word separators.
Normally, the title of the page should be the first line of the file, underlined with equal-signs.

Title of Page
================

Page content is here...

You can alternatively wrap the title in two lines of asterisks, in some cases. (This should
not be your default choice.)

*******************
Title of Page
*******************

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 555
Chapter 28. Contributing to ODK Docs

Page content here.

The asterisks style is useful when you are combining several existing documents and don’t
want to change every subsection headline. Or, you can use it when you are working on
a document that you have reason to think might be split into separate documents in the
future.

Important: If you use the double-asterisks style, your major section headlines (<h2>)
should use the equal-signs underline style. This allows major sections to be easily promoted
to individual pages.

See Sections and Titles for more details.

28.2.3 Tables of Content

The toctree directive defines a table of content. The content of a toctree is a list of page
file names, without the .rst extension. When rendered, the toctree becomes an unordered
list of page links, including links to sections and subsections of the included pages.

.. toctree::

page-name
another-page
this-other-page

The depth of section and subsection links to display in the output can be controlled using
the maxdepth attribute. We typically use a depth of 2, but you should use your judgment if
you feel it should be more or less in any given context.

.. toctree::
:maxdepth: 2

this-page
that-page
thick-page
flat-page

See also:
The TOC Tree
The Sphinx documentation includes information about a number of other
toctree attributes.

556 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

Sidebar navigation menu

The index.rst file serves as a front-page to the documentation and contains the main tables
of content, defined using toctree directives.
These toctree directives control the sidebar navigation menu. To add a new document to
a table of content, add the file name (without the .rst extension) to the relevant list of file
names in index.rst.

Secondary tables of content

Collections of documents are sometimes given their own table of content on an individual
page. (See, for example, Setting Up ODK Collect and Using ODK Collect.)
In these cases, the page containing the toctree serves as a sort of intro page for the collection.
That intro must, itself, be included in the Sidebar navigation menu.
The contents of a toctree appear as section links in another toctree it is included in. That
is, if a toctree in index.rst lists collect-using, and collect-using.rst has a toctree,
then the contents of that second toctree will appear in the Sidebar navigation menu, as
sub-items to Using ODK Collect. (Indeed, this is precisely the case in the docs currently.)

How ODK Docs uses main and secondary tables of content

• Major topics get a toctree in index.rst


Major topics include things like:
– Each major product (Collect, Aggregate, Briefcase)
– Large, general categories like Contributing
Major topic tables of content include both sub-collection intro pages and also individual
pages that don’t fit into a sub-collection.
The caption attribute of the toctree directive defines the section label in the Sidebar
navigation menu.
• Within a large topic, documents are grouped into collections of related pages, defined
by a toctree on a topic intro page.
Intro pages (pages that contain secondary toctree directives) may include additional
content, introducing the collection or providing contextual wayfinding. However, this
is not always necessary or desirable. Use your judgment, and avoid stating things just
for the sake of having some text. (”Here are the pages in this collection.”)
We also (very occasionally) include toctree directives in sub-collection pages.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 557
Chapter 28. Contributing to ODK Docs

Tip: If it not obvious where a new document should appear in the navigation, the best
practice is to simply ask about it in the GitHub issue driving the new page.

Note: For wayfinding purposes, we sometimes create an Unordered (bullet) lists of page
links rather than a toctree directive. (For example, see collect-intro. We do this when
using a toctree would create redundant links in the Sidebar navigation menu.

Why are the docs files not grouped into folders in the source?
We use toctree directives as our primary way of organizing the documentation for readers.
We do not organize the source rst files into subfolders.
The reason is that if we put them into topic-related subfolders, it would affect the URI of
the document. Keeping all of our document files in a single flat directory results in a flat
URI structure. Every page’s URI looks like docs.getodk.org/page-name.
If we used subdirectories, then our URIs would look like docs.getodk.org/
subdirectory-name/page-name. This would mean that our URIs would change every time
we moved a document from one folder to another, greatly increasing the time cost and
broken-link risk of reorganizing the docs.

28.2.4 Sections and Titles

Headlines require two lines:


• the text of the headline, followed by
• a line filled with a single character.
Each level in a headline hierarchy uses a different character:

Title of the Page - <h1> - Equal Signs


=========================================

Major Section - <h2> - Hyphens


---------------------------------

Subsection - <h3> - Tildes


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

558 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

Sub-subsection - <h4> - Double Quotes


"""""""""""""""""""""""""""""""""""""""

Sub-sub-subsection - <h5> - Single Quotes


''''''''''''''''''''''''''''''''''''''''''''

If you need to combine several existing pages together, or want to start a single-page doc
that you think might be split into individual pages later on, you can add a top-level title,
demoting the other headline types by one.

************************************************
Page Title - <h1> - Asterisks above and below
************************************************

Major Section - <h2> - Equal Signs


=======================================

Subsection - <h3> - Hyphens


---------------------------------

Sub-subsection - <h4> - Tildes


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sub-sub-subsection - <h5> - Double Quotes


"""""""""""""""""""""""""""""""""""""""""""""

Sub-sub-sub-subsection - <h6> - Single Quotes


''''''''''''''''''''''''''''''''''''''''''''''''''

In either case, the underline of characters needs to be longer than the line of text. In the
case of the asterisks, the two lines of asterisks need to be the same length.

Note: The exact order of underline characters is flexible in reStructuredText. However,


this specific ordering should be used throughout the ODK documentation.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 559
Chapter 28. Contributing to ODK Docs

Section labels

In order to facilitate efficient Cross referencing, sections should be labeled. This is done on
the line above the section title. The format is:
• two dots
• underscore
• section label
– lowercase
– hyphen separators
• a single colon

.. _section-label:

Section Title
----------------

Lorem ipsum content of section blah blah.

The section label is usually a slugified version of the section title.


Section titles must be unique throughout the entire documentation set. Therefore, if you
write a common title that might appear in more than one document (Learn More or Getting
Started, for example), you’ll need to include additional words to make the label unique. The
best way to do this is to add a meaningful work from the document title.

ODK Aggregate
===============

ODK Aggregate is a server application...

.. _aggregate-getting-started:

Getting Started
-----------------

28.2.5 Basic Markup

Escaping characters

Markup characters can be escaped using the \ character.

560 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

*Italic.*

\*Not italic, surrounded by asterisks.\*

Italic.
*Not italic, surrounded by asterisks.*

Emphasis and Inline Literal

Single asterisks for *italic text* (``<em>``).

Double asterisks for **bold text** (``<strong>``).

Double back-ticks for ``inline literal text`` (``<code>``).

Single asterisks for italic text ( <em> ).


Double asterisks for bold text ( <strong> ).
Double back-ticks for inline literal text ( <code> ).

Note: The bold, italic, and inline literal styles do not carry semantic meaning. They
should not be used when a more semantically appropriate markup construct is available; for
example, when writing about GUI text.

Hyperlinks

External hyperlinks — that is, links to resources outside the documentation — look like
this:

This is a link to `example <http://example.com>`_.

This is a link to example.


You can also use ”reference style” links:

This is a link to `example`_.

.. _example: http://example.com

This may help make paragraphs with a lot of links more readable. In general, the inline
style is preferable. If you use the reference style, be sure to keep the link references below
the paragraph where they appear.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 561
Chapter 28. Contributing to ODK Docs

You can also simply place an unadorned URI in the text: http://example.com

You can also simply place an unadorned URI in the text: http://example.com

Lists

Unordered (bullet) lists

Bulleted lists ( ``<ul>`` ):

- use hyphens
- are unindented at the first level
- must have a blank line before and after

- the blank line requirement means that nested list items will have a blank␣
,→line before and after as well

- you may *optionally* put a blank line *between* list items

Bulleted lists ( <ul> ):


• use hyphens
• are unindented at the first level
• must have a blank line before and after
– the blank line requirement means that nested list items will have a blank line
before and after as well
– you may optionally put a blank line between list items

Ordered (numbered) lists

Numbered lists ( ``<ol>`` ):

1. Start each line with a number and period


2. Can begin on any number
3. Must have a blank line before and after
4. Can have nested sub-lists

a. nested lists are numbered separately


b. nested lists need a blank line before and after

#. Can have automatic number with the ``#`` character.

562 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

Numbered lists ( <ol> ):


1. Start each line with a number and period
2. Can begin on any number
3. Must have a blank line before and after
4. Can have nested sub-lists
(a) nested lists are numbered separately
(b) nested lists need a blank line before and after
5. Can have an automatic number with the # character.

Note: See Ordered and unordered lists in the Docs Style Guide for details on when to use
ordered and unordered lists.

Definition Lists

Definition list ( ``<dl>`` )


a list with several term-definition pairs

Terms
should not be indented

Definitions
should be indented under the term

Line spacing
there should be a blank line between term-definition pairs

Definition list ( <dl> ) a list with several term-definition pairs


Terms should not be indented
Definitions should be indented under the term
Line spacing there should be a blank line between term-definition pairs

Paragraph-level Markup

Paragraphs are separated by blank lines. Line breaks in the source code do not␣
,→create line breaks in the output.

This means that you *could*, in theory,

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 563
Chapter 28. Contributing to ODK Docs

include a lot of arbitrary line breaks


in your source document files.
These line breaks would not appear in the output.
Some people like to do this because they have been trained
to not exceed 80 column lines, and they like
to write .txt files this way.
Please do not do this.

There is **no reason** to put a limit on line length in source files for␣
,→documentation, since this is prose and not code. Therefore, please do not put␣

,→arbitrary line breaks in your files.

Paragraphs are separated by blank lines. Line breaks in the source code do not create line
breaks in the output.
This means that you could, in theory, include a lot of arbitrary line breaks in your source
document files. These line breaks would not appear in the output. Some people like to do
this because they have been trained to not exceed 80 column lines, and they like to write
.txt files this way. Please do not do this.
There is no reason to put a limit on line length in source files for documentation, since this
is prose and not code. Therefore, please do not put arbitrary line breaks in your files.

Block Quotes

This is not a block quote. Block quotes are indented, and otherwise unadorned.

This is a block quote.


— Adam Michael Wood

This is not a block quote. Block quotes are indented, and otherwise unadorned.
This is a block quote. — Adam Michael Wood

Line Blocks

| Line blocks are useful for addresses,


| verse, and adornment-free lists.
|
| Each new line begins with a
| vertical bar ("|").
| Line breaks and initial indents
| are preserved.

564 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

Line blocks are useful for addresses,


verse, and adornment-free lists.

Each new line begins with a


vertical bar (”|”).
Line breaks and initial indents
are preserved.

Tables

Grid style

+------------+------------+-----------+
| Header 1 | Header 2 | Header 3 |
+============+============+===========+
| body row 1 | column 2 | column 3 |
+------------+------------+-----------+
| body row 2 | Cells may span columns.|
+------------+------------+-----------+
| body row 3 | Cells may | - Cells |
+------------+ span rows. | - contain |
| body row 4 | | - blocks. |
+------------+------------+-----------+

Header 1 Header 2 Header 3


body row 1 column 2 column 3
body row 2 Cells may span columns.
body row 3 Cells may span rows. • Cells
• contain
body row 4 • blocks.

Simple style

===== ===== ======


Inputs Output
------------ ------
A B A or B
===== ===== ======
False False False
True False True

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 565
Chapter 28. Contributing to ODK Docs

False True True


True True True
===== ===== ======

Inputs Output
A B A or B
False False False
True False True
False True True
True True True

CSV Table

The csv-table role is used to create a table from CSV (comma-separated values) data. CSV
is a common data format generated by spreadsheet applications and commercial databases.
The data may be internal (an integral part of the document) or external (a separate file).

.. csv-table:: Example Table


:header: "Treat", "Quantity", "Description"
:widths: 15, 10, 30

"Albatross", 2.99, "On a stick!"


"Crunchy Frog", 1.49, "If we took the bones out, it wouldn't be
crunchy, now would it?"
"Gannet Ripple", 1.99, "On a stick!"

Table 28.1: Example Table


Treat Quantity Description
Albatross 2.99 On a stick!
Crunchy Frog 1.49 If we took the bones out, it wouldn’t be crunchy,
now would it?
Gannet Ripple 1.99 On a stick!

Some of the options recognized are:


:widths:
Contains a comma or space-separated list of relative column widths. The default is
equal-width columns.
The special value auto may be used by writers to decide whether to delegate the
determination of column widths to the backend.

566 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

In most cases, the best result is either the default or auto. If you’re unsure, try it both
ways and see which looks better to you.
:header:
Contains column titles. It must use the same CSV format as the main CSV data.
:delim:
Contains a one character string used to separate fields. Default value is comma. It
must be a single character or Unicode code.
The only reason to use something other than a comma is when copying large blocks of
content from another source that uses a different style. If you are creating new table
content yourself, use the comma.

.. csv-table:: Table using # as delimiter


:header: "Name", "Grade"
:widths: auto
:delim: #

"Peter"#"A"
"Paul"#"B"

.. csv-table:: Table using | as delimiter


:header: "Name", "Grade"
:widths: auto
:delim: |

"Peter"|"A"
"Paul"|"B"

:align:
It specifies the horizontal alignment of the table. It can be left, right or center.

.. csv-table:: Table aligned to right


:header: "Name", "Grade"
:align: right

"Peter", "A"
"Paul", "B"

Table 28.2: Table aligned to right


Name Grade
Peter A
Paul B

:file:
Contains the local file system path to a CSV data file.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 567
Chapter 28. Contributing to ODK Docs

:url:
Contains an Internet URL reference to a CSV data file.

Note:
• There is no support for checking that the number of columns in each row is the same.
However, this directive supports CSV generators that do not insert ”empty” entries at
the end of short rows, by automatically adding empty entries.
.. csv-table:: Table with different number of columns in each row
:header: "Name", "Grade"

"Peter"
"Paul", "B"

Table 28.3: Table with different number of columns in


each row
Name Grade
Peter
Paul B

• Whitespace delimiters are supported only for external CSV files.

For more details, refer to this guide on CSV Tables.

Note: In almost all cases, csv-table is the easiest and most maintainable way to insert a
table into a document. It should be preferred unless there is a compelling reason to use one
of the other styles.

28.2.6 Sphinx-specific Markup

Roles and directives

A role is an inline markup construct that wraps some text, similar to an HTML or XML
tag. They look like this:
:rolename:`some text`

A directive is a block-level markup construct. They look like this:


.. directivename:: additional info or options here
:option: optional-value

568 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

:option: optional-value

Content of block here, indented.

This is no longer part of the block controlled by the directive.

Most of the Sphinx-specific and ODK-specific markup will use one or both of these constructs.

Cross referencing

Cross referencing is linking internally, from one place in the documentation to another. This
is not done using the Hyperlinks syntax, but with one of the several roles:

:role:`target`
becomes...
<a href="target">reference title</a>

:role:`anchor text <target>`


becomes...
<a href="target">anchor text</a>

:doc:
• Links to documents (pages)
• target is the file name, without the .rst extension
• title is the first headline ( <h1> ) of the page
:ref:
• Links to sections
• target is the Section labels
• title is the section title (headline)
:term:
• Links to items in the Glossary
• target is the term, in the glossary
• title is the term itself
To recap: If you do not include an explicit target, the text inside the role will be understood
as the target, and the anchor text for the link in the output will be the title of the target.
For example:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 569
Chapter 28. Contributing to ODK Docs

- Link to this document:

- :doc:`contributing`
- :doc:`anchor text <contributing>`

- Link to this section:

- :ref:`cross-referencing`
- :ref:`anchor text <cross-referencing>`

- Link to a term:

- :term:`participant`
- :term:`anchor text <participant>`

• Link to this document:


– Contributing to ODK Docs
– anchor text
• Link to this section:
– Cross referencing
– anchor text
• Link to a term:
– participant
– anchor text

Writing about User Interface

Several roles are used when describing user interactions.


:guilabel:
Marks up actual UI text of form labels or buttons.

Press the :guilabel:`Submit` button.

:menuselection:
Marks up the actual UI text of a navigation menu or form select element.

Select :menuselection:`Help` from menu.

When writing about multi-level menus, use a single :menuselection: role, and sepa-
rate menu choices with -->.

570 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

To save your file, go to :menuselection:`File --> Save` in the Main Menu.

Note: In some situations you might not be clear about which option (menuselection or
guilabel) to use. GUIs in real life can sometimes be ambiguous. The general rule is:
• Actual UI text will always receive guilabel role unless the text could reasonably be
understood to be part of a menu.
• If the actual UI text could be understood as a menu, menuselection should be used.
These both render the same on output, so don’t worry too much if you get it wrong. Just
use your judgment and take your best guess.

:kbd:
Marks up a sequence of literal keyboard strokes.

To stop the local server, type :kbd:`CTRL C`.

:command:
Marks up a terminal command.

To build the documentation, use :command:`sphinx-build`.

:option:
Marks up a terminal command option.

The :option:`-b html` option specifies the HTML builder.

:gesture:
Describes a touch screen gesture.

:gesture:`Swipe Left`

Writing about forms

We have added several custom text roles for writing about forms and the XForms and
XLSForm formats.
:th:
Used to refer to a table header cell.
:tc:
Used to refer to a table cell.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 571
Chapter 28. Contributing to ODK Docs

External App String Widget


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The external app widget is displayed when the :th:`appearance` attribute␣
,→begins with :tc:`ex:`.

:formstate:
Specifies the state of the form in ODK Collect, which could be one of the following:
• Blank
• Finalized
• Saved
• Sent
• Deleted

:formstate:`Sent`

Other Semantic Markup

:abbr:
Marks up an abbreviation. If the role content contains a parenthesized explanation, it
will be treated specially: it will be shown in a tool-tip in HTML.

:abbr:`ODK`

:dfn:
Marks the defining instance of a term outside the glossary.

:dfn:`ODK` is a suite of open source applications that help organizations␣


,→engaged in enumerator-mediated data collection.

:file:
Marks the name of a file or directory. Within the contents, you can use curly braces
to indicate a ”variable” part.

is installed in :file:`/usr/lib/python2.{x}/site-packages`

In the built documentation, the x will be displayed differently to indicate that it is


variable.
:program:
Marks the name of an executable program.

572 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

launch the :program:`ODK Aggregate Installer`

Images and Figures

PNGs only

All still images used in ODK Docs should be PNG files. This helps us keep our image
compression tooling simple, and generally results in higher-quality screenshots.
Whenever possible, you should generate your images as PNGs rather than converting to
PNGs from another format. If you have to start in another format, use lossless formats
whenever possible. These include BMP, GIF, and TIFF. (Avoid JPG/JPEG if possible, as
this is a lossy format that does not replicate screenshots very well.)

Where to put image files

Image files should be put in the /src/img/ directory in the source, and they should be in
a subdirectory with the same name as the document in which they appear. (That is, the
filename without the .rst extension.)

Image compression

Before committing images locally, run lossless compression on them using one of the following
tools:
• ImageOptim
• Pngout

Inserting images in a document

To place an image in a document, use the image directive.

.. image:: /img/{document-subdirectory}/{file}.*
:alt: Alt text. Every image should have descriptive alt text.

Note the literal asterisk (*) at the end, in place of a file extension. Use the asterisk, and
omit the file extension.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 573
Chapter 28. Contributing to ODK Docs

Inserting images with captions (figures)

Use figure to markup an image with a caption.

.. figure:: /img/{document-subdirectory}/{file}.*
:alt: Alt text. Every image should have descriptive alt text.

The rest of the indented content will be the caption. This can be a short␣
,→sentence or several paragraphs. Captions can contain any other rst markup.

Inline images

To information on creating inline images, see Substitutions.

Image File Names

Image file names should:


• be short yet descriptive
• contain only lower case characters and (in Sequentially numbered images only) numbers
• have no spaces
• use hyphens as the separator
Good image file names:
• collect-home-screen.png
• build-data-export-menu.png
Bad image file names:
• Collect home screen.png
• collect_home_screen.png
• 3987948p2983768ohl84692p094.jpg-large

Sequentially numbered images

In the case of sequentially numbered images, the numbers should:


• be zero-indexed
• have two digits with leading zeroes

574 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

• be separated from the rest of the file name with a hyphen


• be placed at the end of the file name
Good sequentially numbered image file names:
• map-widget-00, map-widget-01, map-widget-02
Bad sequentially numbered image file names:
• 1-map-widget, 2-map-widget
• map-widget_00, map-widget_01
• map-widget-1, map-widget-2

Screenshots from ODK Collect

If you have set up Android Debug Bridge, you can connect your Android device to your
computer and take screenshots from the command line.
• Connect your device via USB
• Enable Developer Settings
– Settings → About phone
– Tap Build number seven (7) times
• Turn on USB Debugging
– Settings → Developer options → USB debugging
Now, at the command line, from the root directory of the odk-docs repo:

python ss.py {document-name}/{image-name}

• {document-name} is the filename (without extension) where the image will be used.
• {image-name} is the name (without extension) given to the image. - follow the Image
File Names guidelines

Warning: Make sure you do not overwrite an existing image.

Tip: If you have a problem running ss.py, check to make sure your Python 3 virtual
environment is activated.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 575
Chapter 28. Contributing to ODK Docs

Tip: Be sure to obscure any personally-identifiable information from screen shots. Crop to
the smallest relevant screen area. Annotate screen shots with arrows or circles to indicate
relevant information.

Videos

Video files should be put in the /src/vid/ directory in the source, and they should be in
a subdirectory with the same name as the document in which they appear. (That is, the
filename without the .rst extension.)
The purpose of on page videos is to illustrate complicated user interactions that might be
difficult to describe otherwise. Longer tutorial videos should be hosted elsewhere and, if
appropriate, linked to from the docs. Therefore:
• The length of the videos must be less than a minute.
• Videos should have no audio.
To insert a video, use the custom video directive.
.. video:: path/to/video
Specify the source path of the video and a descriptive alt content in the video directive.
Alternate content is displayed when the video cannot be played. It can contain long
texts as well as any other rst content.

.. video:: /vid/{document-subdirectory}/{file}.ext

Alt content. Every video should have descriptive alt content.

The following optional attributes are supported:


:autoplay:
Specifies whether the video should start playing as soon as it is ready. Can take
boolean value: true, false, yes or no. Default is no.
It is almost never a good idea to turn autoplay on.
:controls:
Specifies whether the video controls should be displayed. Can take boolean value:
true, false, yes or no. Default is yes.
:muted:
Specifies whether the audio output of the video should be muted. Can take
boolean value: true, false, yes or no. Default is yes.
:loop:
Specifies whether the video should start over again, every time it is finished. Can

576 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

take boolean value: true, false, yes or no. Default is no.


:preload:
Specifies if and how the author thinks the video should be loaded when the page
loads. Can take one of the following three values: auto, metadata or none.
:poster:
Contains the source address for an image to be shown while the video is down-
loading, or until the user hits the play button.

Note: Images to be used as poster for a video should be in the same directory as
the video and should have a filename like [same-file-name-as-video]-poster.
ext.

:class:
Specifies a class for the video element.
For more details on these attributes, see this guide.
To add a video in a document with the above options, you can do the following:

.. video:: /vid/{document-subdirectory}/{file}.ext
:autoplay: yes/no
:controls: yes/no
:muted: yes/no
:loop: yes/no
:class: class-name
:preload: auto/metadata/none
:poster:: /vid/{document-subdirectory}/{file}.ext

Alt content. Every video should have descriptive alt content.

Capturing video from Android

Android Debug Bridge (ADB) can be used to capture a screen recording from an Android
app.

$ adb shell screenrecord /sdcard/example.mp4

On pressing the enter key the video recording starts. Recording stops automatically after 3
minutes. Since videos have to be less than a minute, press CTRL C to stop the recording.
The video file is saved in your Android device to a file at /sdcard/example.mp4 file.
To pull the video locally:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 577
Chapter 28. Contributing to ODK Docs

$ adb pull /sdcard/example.mp4 local/path/to/save/to

Downloadable files

Downloadable files should be put in the /src/downloads/ directory in the source, and they
should be in a subdirectory with the same name as the document in which they appear.
(That is, the filename without the .rst extension.)
To place a downloadable file in a document, use the download role.

See this :download:`example script </downloads/contributing/example_script.py>`␣


,→to understand the procedure better.

Code Samples

Use the code-block directive to insert code samples. Specify the language on the same line
as the directive for syntax highlighting.

.. code-block:: rst

Use the ``code-block`` directive to markup code samples.

.. code-block:: python

print("Hello ODK!")

.. code-block:: console

$ python --version

.. code-block:: java

public class HelloWorld {

public static void main(String[] args) {


// Prints "Hello, World" to the terminal window.
System.out.println("Hello, World");
}

Note: rst code-blocks wrap overflow lines by default. To unwrap overflow lines, use
unwrap class with rst code-blocks.

578 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.2. Docs Markup and Syntax Guide

.. code-block:: rst
:class: unwrap

Code-blocks for other languages don’t wrap overflow lines. Instead of wrapping, you need to
scroll side-ways. To wrap overflow lines with other code-blocks, use wrap class with them.

.. code-block:: python
:class: wrap

Substitutions

Substitutions are a useful way to define a value which is needed in many places.
Substitution definitions are indicated by an explicit markup start (”.. ”) followed by a vertical
bar, the substitution text (which gets substituted), another vertical bar, whitespace, and the
definition block.
A substitution definition block may contain inline-compatible directives such as image or
replace. For more information, refer this guide.
You can define the value once like this:

.. |RST| replace:: reStructuredText

and then reuse it like this:

We use |RST| to write documentation source files.

Here, |RST| will be replaced by reStructuredText


You can also create a reference with styled text:

.. |slack| replace:: **ODK Slack**


.. slack: https://getodk.slack.com

You can use the hyperlink reference by appending a ”_” at the end of the vertical bars, for
example:

You can ask about your problem in |slack|_.

You can ask about your problem in ODK Slack.


The rst_epilog in conf.py contains a list of global substitutions that can be used from
any file. The list is given below:
• If you want to create a hyperlink reference for ODK Slack, you can use |odk-slack|_.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 579
Chapter 28. Contributing to ODK Docs

You can use |odk-slack|_ to ask your questions.

You can use ODK Slack to ask your questions.

• To create a hyperlink reference for docs related issues, use |docs-issue|_.

If you find a problem, file an |docs-issue|_.

If you find a problem, file an issue.

• To create a hyperlink reference for ODK Forum, use |forum|_.

You can ask support questions in |forum|_.

You can ask support questions in ODK Forum.

• To create a hyperlink reference for contributors guide, use |contrib-guide|_.

Be sure to read the |contrib-guide|_.

Be sure to read the contributors guide.


You can add inline images in the document using substitutions. The following block of code
substitutes arrow in the text with the image specified.

The |arrow| icon opens the jump menu.

.. |arrow| image:: /img/{document-subdirectory}/{file}.*


:alt: Alt text.

580 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

28.3 Docs Style Guide

28.3.1 Spelling and grammar

American spelling and grammar

Whenever U.S. English and British (or other) English spelling or usage disagree, standard
U.S. spelling and usage is preferred.

Wrong

The colour of the button is grey.

Right

The color of the button is gray.

@memoize
def check_ukus(text):
"""UK vs. US spelling usage."""
err = "style-guide.uk-us"
msg = "uk-vs-us-spell-check. '{}' is the preferred spelling."

preferences = [
["gray", ["grey"]],
["color", ["colour"]],
["accessorizing", ["accessorising"]],
["acclimatization", ["acclimatisation"]],
["acclimatize", ["acclimatise"]],
["acclimatized", ["acclimatised"]],
]

return preferred_forms_check(text, preferences, err, msg)

# This is a sample code. The complete code can be found in the file:
# proselint-extra.py.

Quote marks

• Quote marks should generally be avoided if possible.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 581
Chapter 28. Contributing to ODK Docs

• Smart quotes (also known as curly quotes or directional quotes) are not permitted in
source files.

Avoid quote marks

Quote marks are used in prose writing to indicate verbatim text. This is rarely useful in
technical writing, as verbatim text usually requires a more specific semantic markup.

Wrong

Click the button that says, "Save."

Right

Click :guilabel:`Save`.

Wrong

You may see an error message that says, "Something went wrong."

Right

You may get an error: ``Something went wrong.``

def check_quotes(text):
"""Avoid using straight quotes."""
err = "style-guide.check-quote"
msg = "Avoid using quote marks."
regex = r"\"[a-zA-z0-9 ]{1,15}\""

errors = []

for matchobj in re.finditer(regex, text):


start = matchobj.start()+1
end = matchobj.end()
(row, col) = line_and_column(text, start)
extent = matchobj.end()-matchobj.start()
errors += [(err, msg, row, col, start, end,

582 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

extent, "warning", "None")]

return errors

Straight quotes

Any time that you do need to use quotation marks, use straight (or plain) quotes. Sphinx
and Docutils will output the typographically correct quote style.

def check_curlyquotes(text):
"""Do not use curly quotes."""
err = "style-guide.check-curlyquote"
msg = "Do not use curly quotes. If needed use straight quotes."
regex = r"\“[a-zA-z0-9 ]{1,15}\”"

errors = []

for matchobj in re.finditer(regex, text):


start = matchobj.start()+1
end = matchobj.end()
(row, col) = line_and_column(text, start)
extent = matchobj.end()-matchobj.start()
errors += [(err, msg, row, col, start, end,
extent, "warning", "None")]

return errors

Serial comma

In a comma-delineated list of items, the penultimate item should be followed by a comma.

Wrong

Apples, oranges and pears.

Right

Apples, oranges, and pears.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 583
Chapter 28. Contributing to ODK Docs

@memoize
def check_comma(text):
"""Use serial comma after penultimate item."""
err = "style-guide.serial-comma"
msg = "Use serial comma after penultimate item."
regex = "\,\s[a-zA-Z0-9]+\sand\s"

return existence_check(text, [regex], err, msg, require_padding=False)

A bulleted list is often more clear than an inline list.

Correct

You will need to be familiar with git, GitHub, and Python.

Possibly Better

You will need to be familiar with:

- git
- GitHub
- Python

There’s no hard rule about which to use in any situation. Use your judgement: try it both
ways and see which is more clear.

Direct Address

Direct address — speaking directly to the reader using the second person ”you” — is pre-
ferred over passive voice (”it can be done”), first-person plural (”we can do it”), or other
constructions.
First person plural (”we”) should only be used when speaking of the ODK project team
(”We recommend…”).

Ordered and unordered lists

An ordered list is numbered. It should be used when the order of the list is essential. For
example, when enumerating a series of steps in a procedure.

584 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

Wrong

- First we do this.
- And then we do this.
- And then we do this.

Right

1. Do this.
2. Do this.
3. Do this.

An unordered list is bulleted. It should be used for a collection of items in which order is
not essential.

Wrong

1. apples
2. oranges
3. bananas

Right

- apples
- oranges
- bananas

Avoid Latin

Several Latin abbreviations are common in written English:


At best, these present a minor barrier to understanding. This is often made worse by
unintentional misuse.
Avoid Latin abbreviations.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 585
Chapter 28. Contributing to ODK Docs

Wrong

If you are writing about a specific process (e.g., installing an application)...

Right

If you are writing about a specific process (for example, installing an␣
,→application)...

@memoize
def check_latin(text):
"""Avoid using Latin abbreviations."""
err = "style-guide.latin-abbr"
msg = "Avoid using Latin abbreviations like \"etc.\", \"i.e.\"."

list = [
"etc\.", "etc", "\*etc\.\*", "\*etc\*",
"i\.e\.", "ie", "\*ie\.\*", "\*ie\*",
"e\.g\.", "eg", "\*eg\.\*", "\*eg\*",
"viz\.", "viz", "\*viz\.\*", "\*viz\*",
"c\.f\.", "cf", "\*cf\.\*", "\*cf\*",
"n\.b\.", "nb", "\*nb\.\*", "\*nb\*",
"q\.v\.", "qv", "\*qv\.\*", "\*qv\*",
"ibid\.", "ibid", "\*ibid\.\*", "\*ibid\*",
]

return existence_check(text, list, err, msg, ignore_case=True)

Etc.

Et cetera (or etc.) deserves a special mention.


Et cetera means ”and all the rest,” and is often used to indicate that there is more that could
or should be said, but which is being omitted.
Writers often use etc. to gloss over details of the subject which they are not fully aware of.
If you find yourself tempted use etc., ask yourself if you really understand the thing you are
writing about.

586 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

Avoid unneeded words

Adverbs

Adverbs often contribute nothing. Common offenders include:


• simply
• easily
• just
• very
• really
• basically
• extremely
• actually

Wrong

To open the file, simply click the button.

Right

To open the file, click the button.

Wrong

You can easily edit the form by...

Right

To edit the form...

@memoize
def check_adverb(text):
"""Avoid using unneeded adverbs."""
err = "style-guide.unneed-adverb"

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 587
Chapter 28. Contributing to ODK Docs

msg = "Avoid using unneeded adverbs like \"just\", \"simply\"."

list = [
"simply",
"easily",
"just",
"very",
"really",
"basically",
"extremely",
"actually",
]

return existence_check(text, list, err, msg, ignore_case=True)

Filler words and phrases

Many words and phrases provide no direct meaning. They are often inserted to make a
sentence seem more formal, or to simulate a perceived style of business communication.
These should be removed.
Common filler phrases and words include:
• to the extent that
• for all intents and purposes
• when all is said and done
• from the perspective of
• point in time
This list is not exhaustive. These ”canned phrases” are pervasive in technical writing. Re-
move them whenever they occur.
@memoize
def check_filler(text):
"""Avoid using filler phrases."""
err = "style-guide.filler-phrase"
msg = "Avoid using filler phrases like \"to the extent that\"."

list = [
"to the extent that",
"when all is said and done",
"from the perspective of",
"point in time",
]

588 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

return existence_check(text, list, err, msg, ignore_case=True)

Semicolons

Semicolons are used to separate two independent clauses which could stand as individual
sentences but which the writer feels would benefit by close proximity.
Semicolons can almost always be replaced with periods (full stops). This rarely diminishes
correctness and often improves readability.

Correct

These "canned phrases" are pervasive in technical writing; remove them whenever␣
,→they occur.

Better

These "canned phrases" are pervasive in technical writing. Remove them whenever␣
,→they occur.

@memoize
def check_semicolon(text):
"""Avoid using semicolon."""
err = "style-guide.check-semicolon"
msg = "Avoid using semicolon."
regex = ";"

return existence_check(text, [regex], err, msg, require_padding=False)

Pronouns

Third-person personal pronouns

Third-person personal pronouns are:


• he/him/his
• she/her/her(s)
• they/them/their(s)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 589
Chapter 28. Contributing to ODK Docs

Note: While some people consider they/them/their to be non-standard (or ”incorrect”)


as third-person singular, it has gained wide use as a gender-neutral or gender-ambiguous
alternative to he or she.

There are two issues with personal pronouns:


• gender bias
• clarity
To avoid gender bias, the third person gender-neutral they/then/their(s) is preferred over he
or she pronouns when writing about abstract individuals.

Wrong

The enumerator uses his device.

Right

The enumerator uses their device.

Unfortunately, they/them/their is not a perfect solution. Since it is conventionally used as


a plural pronoun, it can cause confusion.
Therefore, avoid the use of personal pronouns whenever possible. They are often out of place
in technical writing anyway. Rewriting passages to avoid personal pronouns often makes the
writing more clear.

Correct

When using Collect, first the enumerator opens the app on their device. Then␣
,→they complete the survey.

Better

To use Collect:

- open the app


- complete the survey

590 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

@memoize
def check_pronoun(text):
"""Avoid using third-person personal pronouns."""
err = "style-guide.personal-pronoun"
msg = "Avoid using third-person personal pronouns like \"he\", \"she\". In␣
,→case of absolute need, prefer using \"they\"."

list = [
"he",
"him",
"his",
"she",
"her",
"hers",
]

return existence_check(text, list, err, msg, ignore_case=True)

”Same”

Same, when used as an impersonal pronoun, is non-standard in Modern American English.


It should be avoided.

Wrong

ODK Collect is an Android app. The same can be used for...

Right

ODK Collect is an Android app. It can be used for...

Right

ODK Collect is an Android app that is used to...

@memoize
def check_same(text):
"""Avoid using impersonal pronoun same."""
err = "style-guide.check-same"

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 591
Chapter 28. Contributing to ODK Docs

msg = "Avoid using \"The same\"."


regex = "\. The same"

return existence_check(text, [regex], err, msg, ignore_case=False,


require_padding=False)

Titles

Title case and sentence case

Document titles should be in Title Case – that is, all meaningful words are to be capitalized.
Section titles should use Sentence case – that is, only the first word should be capitalized,
along with any proper nouns or other words usually capitalized in a sentence.

Verb forms

If a document or section describes a procedure that someone might do, use a verb ending in
-ing. (That is, a gerund.) Do not use the ”How to…” construction.

Wrong

How to install ODK Collect


--------------------------

Right

Installing ODK Collect


----------------------

If section title is a directive to do something (for example, as a step in a procedure), use an


imperative.

Installing ODK Aggregate


------------------------

Download ODK Aggregate


~~~~~~~~~~~~~~~~~~~~~~

Section content here.

592 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

@memoize
def check_howto(text):
"""Avoid using how to construct."""
err = "style-guide.check-howto"
msg = "Avoid using \"How to\" construction."
regex = "(How to.*)(\n)([=~\-\"\*]+)"

return existence_check(text, [regex], err, msg, require_padding=False)

Section labels

Section titles should almost always be preceded by labels.


The only exception is very short subsections that repeat — like the Right and Wrong titles
in this document or the XLSForm Rows and XForm XML sections in the Question Types
document.
In these cases, you may want to use the rubric directive.
def check_label(text):
"""Prefer giving a section label."""
err = "style-guide.check-label"
msg = "Add a section label if required."
regex = r"(.*\n)(( )*\n)(.+\n)(([=\-~\"\']){3,})"

errors = []
sym_list = ['===','---','~~~','"""','\'\'\'']
is_doc_title = True

for matchobj in re.finditer(regex, text):


if is_doc_title:
is_doc_title = False
continue
label = matchobj.group(1)
start = matchobj.start()+1
end = matchobj.end()
(row, col) = line_and_column(text, start)
row = row + 2
if any(word in text.splitlines(True)[row] for word in sym_list):
row = row - 1
col = 0
extent = matchobj.end()-matchobj.start()
catches = tuple(re.finditer(r"\.\. _", label))
if not len(catches):
errors += [(err, msg, row, col, start, end,
extent, "warning", "None")]

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 593
Chapter 28. Contributing to ODK Docs

return errors

Other titling considerations

• Do not put step numbers in section titles.


• Readers skim. Section titles should be clear and provide information.

28.3.2 Writing code and writing about code

ODK Documentation includes code samples in a number of languages. Make sure to follow
generally accepted coding style for each language.

Indenting

In code samples:
• Use spaces, not tabs.
• Two spaces for logical indents in most languages.
– Python samples must use four spaces per indent level.
• Strive for clarity. Sometimes nonstandard indentation, especially when combined with
non-syntactic line breaks, makes things easier to read.
– Make sure that line breaks and indentation stay within the valid syntax of the
language.
Using two spaces keeps code sample lines shorter, which makes them easier to view.

Example of indenting for clarity

HTTP/1.0 401 Unauthorized


Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:26:47 GMT
WWW-Authenticate: Digest realm="testrealm@host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
Content-Type: text/html
Content-Length: 311

594 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

Meaningful names

When writing sample code, avoid meaningless names.

Wrong

def myFunction(foo):

for bar in foo:


bar[foo] = foo[spam] + spam[foo]

return foobar

XML and HTML

Some of the terms often used to describe XML and HTML code structures are imprecise or
confusing. For clarity, we restrict certain terms and uses.
Likewise, coding practices and styles for XML and HTML vary widely. For the sake of clarity
and consistency, samples should follow the guidelines set forth here.

Element

The following piece of code represents an element:

<element>
Some content.
</element>

Note: An element is not a block or a tag.


• Tag is defined below.
• Block has a specific meaning in HTML and XML templates, and should generally be
avoided outside those contexts.

Tag

A tag is the token that begins or ends an element.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 595
Chapter 28. Contributing to ODK Docs

<element> <!-- The opening tag of this element. -->


Some content.
</element> <!-- The closing tag. -->

The word tag has often been used to refer to the entire element. For clarity, we will avoid
that here.

Node

The word node is often used interchangeably with element.


For clarity, we make the following distinction:
• An HTML or XML document has elements, not nodes.
• A node is part of a ”live” DOM tree or other dynamic representation.
– An XML or HTML element becomes an element node in a DOM tree.
– There are also other types of nodes in a DOM tree.

Attributes and values

An element may have attributes. Attributes have values. Values are wrapped in straight
double-quotes.

<element attribute="value">
Content.
</element>

Other names for attributes, such as variables or properties, should be avoided.

Element content

The code between the opening and closing tags of an element is the content. Content can
include other elements, which are called child elements.

<element>
Content.
<child-element>
More content.
</child-element>
</element>

When an element is empty, it can be called a null element.

596 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

<null-element attribute="value" />

In XML, null element tags always self-close. This is not the case in HTML.
• HTML elements that are always null (for example, <img>) do not need to be self-
closed.
• Empty HTML elements that normally accept content have a separate closing tag.

<img src="awesome-picture.jpeg">

<script src="some-javascript.js"></script>

Capitalization

For all HTML samples, tag names and attribute names should be all lowercase.
Newly-written XML examples should also be all lowercase.
XML examples that show actual code generated by tools in the ODK ecosystem should
replicate that code exactly, regardless of its capitalization practice.

28.3.3 ODK jargon

ODK and ODK Docs

Wrong

• Odk
• odk
• OpenDataKit
• the ODK
• ODK docs
• ODK documentation

Right

• ODK
• getodk

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 597
Chapter 28. Contributing to ODK Docs

• ODK Docs
• ODK Documentation

Probably want to avoid…

• ODK Documentation

@memoize
def check_odkspell(text):
"""ODK spelling usage."""
err = "style-guide.spelling-odk"
msg = "ODK spell check. '{}' is the preferred usage."

preferences = [

["ODK", ["OpenDataKit"]],
["ODK", ["Odk"]],
["ODK", ["{0} odk"]],
["ODK Docs", ["ODK docs"]],
["ODK Documentation", ["ODK documentation"]]
]

return preferred_forms_check(text, preferences, err, msg, ignore_case=False)

ODK app and project names

ODK includes a number of components, including:


• Collect
• Aggregate
• Briefcase
These should always be capitalized.
The ODK prefix (as in, ODK Collect) should be used the first time a document mentions
the app or project, or any other time it would be unclear.
A few projects should always use the ODK prefix:
• ODK XForm
• ODK Javarosa
• ODK Docs

598 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.3. Docs Style Guide

@memoize
def check_appspell(text):
"""ODK spelling usage."""
err = "style-guide.spelling-odk"
msg = "ODK spell check. '{}' is the preferred usage."

preferences = [
["Aggregate", ["{0} aggregate"]],
["Briefcase", ["{0} briefcase"]]
]

return preferred_forms_check(text, preferences, err, msg, ignore_case=False)

XForms and XLSForm

• XForms refers to XML-encoded forms.


• XLSForm refers to a spreadsheet format used to define forms.

Wrong

• Xforms
• X-Forms
• xforms
• XFORMS
• XForm (no s, when referring to the specification)
• xlsform
• XLSform
• Xlsform

Right

• XForms
• an Xform (when referring to a single form)
• XLSForm

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 599
Chapter 28. Contributing to ODK Docs

@memoize
def check_formspell(text):
"""ODK spelling usage."""
err = "style-guide.spelling-odk"
msg = "ODK spell check. '{}' is the preferred usage."

preferences = [
["XForms", ["Xforms"]],
["XForms", ["X-Forms"]],
["XForms", ["{0} xforms"]],
["XForms", ["XFORMS"]],
["an XForm", ["a XForm"]],
["an XLSForm", ["a XLSForm"]],
["XLSForm", ["{0} xlsform"]],
["XLSForm", ["XLSform"]],
["XLSForm", ["Xlsform"]]
]

return preferred_forms_check(text, preferences, err, msg, ignore_case=False)

XForms Spec, XForms Tools, XForms

XForms can refer to:


• The XML-based form format
• The official XForms specification from the W3C
• The ODK XForms Specification, which is a subset of the full W3C recommendation.
• The general idea of an XML-based form.
XForm (without an s) refers to:
• A specific XML document that encodes a form.
When writing about any of these things, make sure you are clear — in your mind as well as
in your writing — which one you are talking about.

XLSForm

XLSForm can refer to:


• The XLSForm format for describing form in an Excel spreadsheet
• A spreadsheet file that describes a form using the format.
• A tool for converting *.xls(x) files to XForm documents.

600 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.4. Docs Developer Guide

When writing about any of these things, make sure you are clear — in your mind as well as
in your writing — which one you are talking about.

28.4 Docs Developer Guide

This document is for contributors working on the design, templating, deployment, or devel-
opment of the ODK Docs website.

28.4.1 Tech Overview

ODK Docs uses:


• Sphinx, a static-site generator written in Python
Sphinx uses:
– Docutils for parsing reStructuredText
– Jinja for templating
• sphinx_rtd_theme, a Sphinx theme/template
sphinx_rtd_theme uses:
– JQuery, a JavaScript library
• Proselint for style testing
• git and GitHub for version control
• CircleCI for testing and deployment
• Amazon S3 for hosting

28.4.2 Custom HTML templating

ODK Docs uses the sphinx_rtd_theme, with some minor customizations.


ODK-specific versions of HTML/Jinja templates are in _templates. Any file in that direc-
tory will override the file of the same name in the sphinx_rtd_theme source.
So, to customize a portion of the HTML template, copy the source file from
sphinx_rtd_theme and then edit it.
Please commit the copied file unchanged before editing, so that it is easy to track what you
have changed.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 601
Chapter 28. Contributing to ODK Docs

28.4.3 Custom JavaScript

Custom JavaScript should be added in src/_static/js/custom.js. Comment your code


with an explanation of what the JS accomplishes, and a reference to the issue number you
are working on.
The ODK Docs template includes JQuery, so you can use it in your custom JS.

28.4.4 Custom CSS

Custom CSS should be added in src/_static/css/custom.css. Comment your code with


an explanation of what the CSS accomplishes and a reference to the issue number you are
working on.
For example:

/* Example CSS PR #xyx */

div[class^='example'] {
color: black;
}

It is helpful to keep the CSS file organized. There are several sections in the custom.css
file:
• Styling for rst roles and directives
• Responsive CSS
• Styling for JS implementation
• Utility classes
Each of these sections are enclosed in start and end comments. Add your code to the relevant
section. If you don’t find any section relevant, add a new section and add your code there.
For example:

/* New section starts */

/* Example CSS PR #xyx */

div[class^='example'] {
color: black;
}

/* New section ends */

602 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.4. Docs Developer Guide

28.4.5 Style Guide checks

Proselint is used for style testing the docs. Apart from the built-in tests in proselint, custom
checks are added for style guide testing. Following a literate programming. model, style
checks are defined in docs-style-guide.rst. After each style rule, you can define a python
code-block containing the code for style testing. When the style-test script is run, these
python code-blocks are parsed to generate a testing script.

Proselint dependent checks

In most of the custom checks, a new function is written that calls one of the built-in proselint
functions as a return value.
All the checks use a decorator memoize() to cache the check for faster execution.
memoize()
Use @memoize above function definition to cache the result.
Proselint provides several functions for defining style tests:
existence_check(text, list, err, msg, ignore_case=True, str=False,
max_errors=float(”inf”), offset=0, require_padding=True,
dotall=False, excluded_topics=None, join=False)
To check for existence of a regex pattern(s) in the text. The parameters offset,
excluded_topics and join are not needed for style guide testing.
Parameters
• text (str) – Text to be checked
• list (list) – List of regex expressions
• err (str) – Name of the test
• msg (str) – Error or warning message
• ignore_case (bool) – For using re.IGNORECASE
• str (bool) – For using re.UNICODE
• max_errors (float) – Maximum number of errors to be generated
• require_padding (bool) – To use padding with the specified regex
(It is better to set it as False and specify the regex accordingly)
• dotall (bool) – For using re.DOTALL
Returns The error list consisting of error tuples: [(start, end, err,
msg, replacement)].
Return type list

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 603
Chapter 28. Contributing to ODK Docs

preferred_forms_check(text, list, err, msg, ignore_case=True, offset=0,


max_errors=float(”inf”))
To suggest a preferred form of the word used. The parameter offset is not needed
for style guide testing.
Parameters
• text (str) – Text to be checked
• list (list) – list of comparison (words or regex): [correct form
, incorrect form]
• err (str) – Name of the test
• msg (str) – Error or warning message
• ignore_case (bool) – For using re.IGNORECASE
• max_errors (float) – Maximum number of errors to be generated
Returns The error list consisting of error tuples: [(start, end, err,
msg, replacement)].
Return type list
consistency_check(text, word_pairs, err, msg, offset=0)
To check for consistency for the given word pairs. The parameters offset is not needed
for style guide testing.
Parameters
• text (str) – Text to be checked
• word_pairs (list) – Word pairs to be checked for consistency
• err (str) – Name of the test
• msg (str) – Error or warning message
Returns The error list consisting of error tuples: [(start, end, err,
msg, replacement)].
Return type list

Note: The checker functions are used by the built-in proselint function lint() to generate
an error list of different format. The returned list finally is: [(check, message, line,
column, start, end, end - start, "warning", replacements)]

See also:
Proselint source code

604 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.4. Docs Developer Guide

Example Usage

@memoize
def example(text):
"""Example check."""
err = "style-guide.example"
msg = "A demonstration for writing checks."
regex = "[\.\?!](example)"

return existence_check(text, [regex], err, msg, ignore_case=False,


require_padding=False)

When you define code-blocks which use built-in proselint testing, specify the class style-
checks.

.. code-block:: python
:class: style-checks

The generated file after parsing code for style checks is style-checks.py.
If the test is too large to be defined in the file docs-style-guide.rst, you can use
a snippet from the test (as here). The code-blocks for such snippets should specify
the class proselint-extra-checks. Define the complete test in the file /style-guide/
proselint-extra-checks.py.

Independent checks

Apart from the checks, which are to be run through proselint, you can add extra checks
to be run independently. They are not enabled in proselintrc as well. For example, the
checks for finding quote marks and section labels do not use any built-in functions to obtain
an error list.

Example Usage

def check_quotes(text):
"""Avoid using straight quotes."""
err = "style-guide.check-quote"
msg = "Avoid using quote marks."
regex = r"\"[a-zA-z0-9 ]{1,15}\""

errors = []

for matchobj in re.finditer(regex, text):


start = matchobj.start()+1

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 605
Chapter 28. Contributing to ODK Docs

end = matchobj.end()
(row, col) = line_and_column(text, start)
extent = matchobj.end()-matchobj.start()
errors += [(err, msg, row, col, start, end,
extent, "warning", "None")]

return errors

The code-blocks for extra checks should specify the class extra-checks. The generated file
after parsing code for extra checks is extra-checks.py.

Note: Built-in proselint function line_and_column() is used with extra checks to obtain
the row and column of the matched text.
line_and_column(text, start)
To find the line number and column of a position in a string.
Parameters
• text (str) – Text to be searched for
• start (int) – Starting position of matched pattern
Returns Tuple containing row and column number
Return type tuple

Error vs warning

• Warnings are intended to provide guidance to authors.


• Errors enforce ”hard” rules, and raising an error will stop the build.
You can classify the result of a check as an error if you are sure that no false positives
would be produced. The checks classified as errors should return a replacement for fixing
the errors. Proselint dependent checks which use the function preferred_forms_check()
or consistency_check() always return a preferred form. If you create an independent
check which generates an error make sure to return a replacement in the error list.
To generate an error from a check, specify the check name in the list of errors in the function
get_errlist() in the file style-test.py.

Excluding built-in proselint checks

To exclude an built-in proselint check, specify the check name in the check list in the function
exclude_checks() in the file style-test.py.

606 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.5. Tips for Making Good Contributions

28.5 Tips for Making Good Contributions

28.5.1 Smallest meaningful PR

A PR should normally address one issue. This makes it easier to review, easier to deploy,
and easier to roll back in case of a problem. Additionally, the smaller the PR, the less likely
it is to create a merge issue.
The exception is when several issues are closely related or can reasonably be worked on
together. In this case, it should be clear by looking at the conversation on the Github issues
that the items are related and will be worked on together. Your PR message should also
make it clear which issues are being worked on, and whether the PR closes the issues or not.
Mention the PR by number:
addresses #123
closes #123

28.5.2 Descriptive PR names

A PR title should answer the question, ”What does this Pull Request do?”
Good PR titles:
• adds a video directive
• makes navigation buttons responsive
• swaps placement of nav buttons and file an issue note
Bad PR titles:
• fix issue
• fix #123
• collect

28.5.3 Small, atomic commits

When working locally, commit often. Don’t wait until you have 100 lines of changes across
multiple files.
• If you need to copy or move a large section or file, commit that change before also
editing it.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 607
Chapter 28. Contributing to ODK Docs

• If you have to create a new template file based on an existing template file, copy the
file in one commit and then work on the changes. This makes it easier to know what
you actually did.
• If writing a new doc, commits after each new section are a good idea.
Commit messages should answer the question, ”What does this commit do?”
Small, well-named commits will help you keep track of your own work and make rollbacks
and other changes easier to deal with.

28.5.4 Discuss issues before working

Take the time to clarify the needs and scope of an issue before committing to work on it.
Especially for coding tasks, make sure you state your understanding and your plan before
working.
If you have a question, ask. Don’t guess.

Note: Many new contributors don’t ask questions because they are worried about appearing
under informed. Please set this worry aside.
You will never be judged harshly for asking clarifying questions or for seeking
more information.

28.5.5 Claim issues

If you decide to work on an issue, let the community know you are working on it by claiming
the issue.
@getodk-bot claim
Once you’ve claimed an issue, other people won’t work on it. So make sure you’re actually
going to work on it before claiming it.
Don’t claim more than one or two open issues at a time.

28.5.6 Share work in progress

It can be helpful to share your in-progress work. To mark a PR as a work in progress, append
WIP: to the beginning of the PR title. We will not merge WIP PRs, and we won’t do a
review on them unless you ask.
If you want a review, comment, opinion, or help on a WIP PR, please tag the relevant
person in the PR comments.

608 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.5. Tips for Making Good Contributions

If you finish the work and want the PR to be merged, you do not need to open a new one.
Just edit the PR title.

28.5.7 If you get stuck while working

• Ask for help in the issue comments. Maybe you can get back on track and complete
the issue.
– Asking questions is always better than guessing.
• Submit a WIP (work in progress) pull request.
– If we can see what progress you have made, it is easier to offer help.
– Even if you don’t complete the task, perhaps someone else can pull in your in-
progress work and build on it.
– Sometimes your in-progress work is an improvement over not having it, and so
we’ll merge in something even if it isn’t complete.
• If you really cannot move forward, it is okay to abandon an issue.

It is okay to abandon an issue

Sometimes you simply cannot complete work you have said you were going to complete.
This could happen because you don’t have all the required skills or knowledge to complete
the work, or because the issue cannot actually be completed as scoped, or because you don’t
have the time.
Please let the community know in the issue discussion.
@getodk-bot unclaim
This way, everyone knows that someone else can take up the project (or that we need to
rethink it).
If you did significant work on a project before abandoning it, consider filing a WIP (work
in progress) PR, so that others can see what you did and potentially build off of it. (Be sure
to mention the issue, so the work is easy to find later.)

28.5.8 If an issue takes a long time to complete

For our purposes, a ”long time” is a week or more, from when you first announce your
intention to work on something until submitting a merge-ready PR.
An issue might take a long time because:
• it is complex and requires lots of hours

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 609
Chapter 28. Contributing to ODK Docs

• you only have a short period of time each day to work on it


• you are new to the project and are having to learn as you go
The thing that matters is: Are you actively working on the issue, and making
progress, at least a little bit?
If you are actively working on it, we do not want someone else to jump on and try to work
on it at the same time. So please keep the community informed of your work by filing a
WIP (work in progress) PR and committing to it as you work.

28.5.9 Issues only

All PRs must be directly connected to open issues. PRs should not represent suggestions,
good ideas, or independent initiative.
If you have a good idea, file an issue. If you are curious about whether something should be
an issue, chat with one of the core team in the #docs-code channel on the Slack.
Once you have filed an issue, wait for comment and approval before diving into the work.
We do not want surprise PRs.

28.5.10 Actually install and use ODK or other tools

You cannot write effectively about tools you have not used. If you’re going to write or edit
documentation about any of the apps in the ODK ecosystem, you need to spend some time
actually using it.
Before diving into writing documentation, try out the core tools here
https://getodk.org/software and become familiar with them.
This is also true of writing about Sphinx or any of our documentation build tools. Reading
existing documentation is not enough to write about something.

And actually do the thing

If you are writing about a specific process (installing an application, for example), you need
to actually complete the process yourself. If possible, follow your own instructions after
writing them to make sure they make sense.

28.5.11 Always build locally

Before submitting a PR, run the build locally to make sure you do not produce any errors
or warnings. We do not accept PRs that produce errors or warnings.

610 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.6. Working with Docs in Windows using Cygwin

It is best to run the build frequently as you work. You’ll often catch simple mistakes that
are harder to track down later.

28.5.12 You are not an impostor

Impostor syndrome is the feeling that you are not good enough or accomplished enough to
do the work you are doing.
We all feel this way sometimes, and that’s okay. But it is important to realize that you are
not an impostor.
You can contribute to this community, no matter your background or skills.
• If there is something you don’t know how to do, you can ask.
– If it is issue related, ask on the issue.
– If it is more general, try the #docs-code channel in the ODK Developer Slack.
• If you want to try something even though you aren’t sure you can do it, go ahead and
try.
Another worry you may have is that something will take you a long time when an ”expert”
might be able to do it quickly. You may feel, then, you aren’t the ”right person” for the
job. But if you are the only one with the time or desire to work on something, you are the
right person to work on it.

28.6 Working with Docs in Windows using Cygwin

The main contribution guide :doc: contributing was built for *nix systems, and the same
commands may not work in Windows. Cygwin is a Windows tool, equivalent to *nix bash
terminal. This guide helps to set up ODK Docs platform from the default Windows command
prompt (CMD).

28.6.1 The prerequisites

The following are software tools that you need in the first place. If it is already installed.
Just follow the steps and apply what is missing.
• Cygwin
• Python 3
• Virtualenv
• Virtualenvwrapper-win

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 611
Chapter 28. Contributing to ODK Docs

• Git and GLFS

28.6.2 The requirements

These are a set of the main packages. ODK team combined them in a file such that all will
be installed at once.
• alabaster==0.7.10
• Babel==2.4.0
• docutils==0.13.1
• imagesize==0.7.1
• Jinja2==2.9.6
• MarkupSafe==1.0
• Pygments==2.2.0
• pytz==2017.2
• requests==2.14.2
• six==1.10.0
• snowballstemmer==1.2.1
• Sphinx==1.6.1
• sphinx-rtd-theme==0.2.4
• sphinxcontrib-websupport==1.0.1
• typing==3.6.1
• update==0.4.4

Install Cygwin

Cygwin tool lets Windows users execute many *nix commands. Install Cygwin and add its
path to Windows to work completely from the default command prompt. For instructions.

Warning: If you encounter any downloading problems, make sure to select a mirror
site near you. The entire list is available on the Cygwin website.

612 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.6. Working with Docs in Windows using Cygwin

Python 3

You need to install Python 3. Select Python installation that fits your system (32 or 64 bit).
For instructions, see.
Make sure to select the option ”Add Python to the Path”, as shown below.

Next, make sure to select ”pip”, which is a package manager <


https://pypi.python.org/pypi/pip>_ written in Python. We will use it to install packages.
See the following image:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 613
Chapter 28. Contributing to ODK Docs

Alternatively, if you forgot to add Python 3 to the PATH, add it manually using the following
command:

> set PATH=%PATH%;C:\Users\your username\python3

Tip: C:/Users/your username/python3 is the default Python 3 installation PATH. If you


change it, please substitute the above path by the new one.

Virtual Environment

A virtual environment tool creates multiple Pythons environments, each has its packages
and dependencies.
For easy installation, pip command can be used, which comes with Python 3 (as shown in
Python installation).

> pip install virtualenv

Create a new directory for your odkdocs work:

> mkdir odk

To work with virtualenv, you have two options:

614 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.6. Working with Docs in Windows using Cygwin

• Use the native virtualenv.


• Use virtualenvwrapper on the top of virtualenv.

Native Virtual Environment

Create a new Python 3 virtual environment, ”odkenv” is the name of the virtualenv, you
can choose any name.

> virtualenv -p <python path/python.exe> odkenv

After creating the virtualenv, multiple files are copied into the folder odkenv in your working
directory.

> ls odkenv

The folder Scripts contains all virtualenv controls as ”.bat” files.


To activate the odkenv:

> cd odkenv
.
.
.
> cd Scripts

> odk/odkenv/Scripts/activate.bat

To deactivate the odkenv:

> odk/odkenv/Scripts/deactivate.bat

Virtual Environment Wrapper

Tip: This step is not an alternative to virtualenv. You must install virtualenv first.

The Virtualenvwrapper <https://pypi.python.org/pypi/virtualenvwrapper-win> mediates be-


tween user CMD and virtualenv to ease management and working with multiple virtual
environments. To install virtualenvwrapper, use the following:

> pip install virtualenvwrapper-win

Create a new virtualenv:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 615
Chapter 28. Contributing to ODK Docs

> mkvirtualenv odkenv

Once the odkenv is created, it is automatically activated:

(odkenv) /odk/docs

To deactivate the odkenv, write:

> deactivate

To activate the odkenv:

> workon odkenv

Git and GLFS

• Install Git for windows. Make sure that git is installed properly by typing (git) in the
CMD.
• Install GLFS.

Android Tools

Install Android Debug Bridge <collect-adb> to learn more about ADB. ADB is part of
Android studio, To download
To use ADB, you must run Android Studio once. The default location of ADB is C:/Users/
your username/AppData/Local/Android/sdk/platform-tools. Add it to Windows PATH
by using the following command:

set PATH=%PATH%;C:\Users\your user␣


,→name\AppData\Local\Android\sdk\platform-tools

Fork and Clone the ODK Docs repo

From Github, fork the ODK Docs. This will create a copy of the docs in your Github account
called origin. Move to the ODk working directory, and clone the ODk Docs into your local
machine.

> git clone https://github.com/your-github-username/docs.git

616 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
28.6. Working with Docs in Windows using Cygwin

Set the Upstream Remote

> git remote add upstream https://github.com/getodk/docs.git

28.6.3 Install the Requirements

This step will install a bunch of packages that are listed in the :file: requirement.txt file.
ODK team prepared this file for you to ease the installation.
First, you need to activate your virtual environment (odkenv):

> workon odkenv

Make sure you are inside the docs folder, then run:

$ pip install -r requirements.txt

You completed the installation and you can start change and build ODK Docs.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 617
Chapter 28. Contributing to ODK Docs

618 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

TWENTYNINE

OPENROSA

OpenRosa is a set of communication standards for moving blank forms and completed form
instances between server applications (like ODK Aggregate) and clients (like ODK Collect).
They were originally worked on by the OpenRosa WorkGroup, and they were an outgrowth
of the JavaRosa project. The working group is no longer active. However, many apps within
the ODK ecosystem (including Collect and Aggregate) continue to implement the API.
This set of docs is intended to provide information about the OpenRosa standards, for use
by developers working on applications that communicate with other applications within the
ODK ecosystem.

29.1 OpenRosa 1.0 APIs

OpenRosa 1.0 APIs were formally approved by the OpenRosa Working Group in December
of 2011. To be considered ”OpenRosa 1.0 Compliant,” a system must implement all 5 of the
OpenRosa 1.0 APIs.

29.1.1 Metadata Scheme

This document details the metadata scheme for OpenRosa-compliant XForms. This meta-
data is used to ensure that critical or extremely useful data pertaining to the XForms and
submissions made by client devices is captured and stored.
There are two types of metadata in a form submission.
• Form metadata — Data about the identity and version of the XForm used to create
the data being submitted.
• Submission metadata — Data about the submission itself.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 619
Chapter 29. OpenRosa

Blank Form Metadata

A blank form must have two pieces of identifying metadata. These are provided as attributes
in the top-level element inside model/instance.

<model>
.
.
.
<instance>
<form-name id="getodk.org:all-widgets" version="2.1.30"
.
.
.
</form-name>
</instance>
</model>

Two attributes are required. One provides the unique identity of the form, the other provides
the current version number.

Form Identity

One of:
• id
• xmlns
These values should be in the form of scheme:value.
If specified, the id value takes precedence over any explicit xmlns declaration.
For id, the implementer’s registered domain name should be used as part of the scheme (for
example:getodk.org:widgetForm).
Compliant systems MUST support id or xmlns lengths up to 249 chars; ideally, servers
SHOULD be able to support arbitrary lengths.

Version

A string value indicating the version number of the form.


• MUST support a string value (not a number), to indicate an increment.
• SHOULD support any string schema.
• MUST support arbitrary strings up to 249 characters

620 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

• SHOULD support arbitrary-length strings


The value of version MUST be incremented when any part of the form changes.
If version is not present, it is handled as NULL.

Completed Form Metadata

In a completed form, metadata is provided in a <meta> element inside the <model> element.

<model>
.
.
.
<meta>
<instanceID>
uuid:ca90905c-a2db-11e7-abc4-cec278b6b50a
</instanceID>
<userID>
openid:http://www.google.com/profiles/adam.michael.wood
</userID>
</meta>

Fields

The only required element in the form submission metadata is <instanceID>, which must
be a universally unique string identifying this specific submission.
Optional fields:
• <timeStart> — An ISO 8601 timestamp of when form entry started.
• <timeEnd> — An ISO 8601 timestamp of when form entry ended.
• <userID> — A unique identifier of the submitting user.
• <deviceID> — A unique identifier of device used to generate the submission.
• <deprecatedID> — the <instanceID> of the submission for which this is a revision.
Server software can use this field to unify multiple revisions to a submission into a
consolidated submission record.

ID field formatting

ID fields (<instanceID>, <userID>, etc.) must follow the format scheme:id.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 621
Chapter 29. OpenRosa

Recommended ID schemes

instanceID, deprecatedID uuid


userID mailto
openid
deviceID mac
uuid
If you implement a custom ID scheme, it should be prefixed with your domain name, to
ensure uniqueness.

<instanceID>getodk.org:123456789</instanceID>

ID Field Constraints

• The combined scheme:value keypair MUST be no longer than 249 characters (ie, so
that varchar(249) can be used).
– A robust Server SHOULD be able to support an arbitrary length ID, however.
• Only ONE of each type of ID element can be included in a form submitted to the server.
That is, only one deviceID, one userID, one instanceID, and one deprecatedID.
– Each ID element MUST have one and only one scheme:value pair.

Defining expected submission metadata in the blank form

The blank form MUST specify which of the metadata fields are expected when the com-
pleted form is submitted. This is done within a <meta> element having the namespace
http://openrosa.org/xforms. The <meta> appears inside the child node of the Primary
Instance (the first instance element inside <model>).

<model>
<instance>
<data xmlns:orx="http://openrosa.org/xforms"
id="example.org:myFormId"
version="1" >
<orx:meta>
<orx:timeStart/>
<orx:timeEnd/>
<orx:instanceID/>
</orx:meta>

622 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

Examples

Blank form metadata

<h:head>
<h:title>Metablock example</h:title>
<model>
<instance>
<data xmlns:orx="http://openrosa.org/xforms"
xmlns="http://example.org/meta"
version="1" >
<orx:meta>
<orx:deviceID/>
<orx:timeStart/>
<orx:timeEnd/>
<orx:instanceID/>
</orx:meta>
.
.
.
</data>
</instance>
.
.
.
</model>
</h:head>

Form submission metadata

<?xml version='1.0'?>
<data version="1"
xmlns:orx="http://openrosa.org/xforms"
xmlns="http://example.org/meta">
<orx:meta>
<orx:deviceID>uuid:38DN0236SAKWJOJNQB3XJI9RW</orx:deviceID>
<orx:timeStart>2010-08-12T04:08:29.765-5:00</orx:timeStart>
<orx:timeEnd>2010-08-12T04:10:23.062-5:00</orx:timeEnd>
<orx:instanceID>uuid.dimagi.org:GEPSJLOGH13TY8L77066GEJJW</orx:instanceID>
<orx:userID>chwid.dimagi.org:Akende</orx:userID>
</orx:meta>
.
.
.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 623
Chapter 29. OpenRosa

</data>

29.1.2 HTTP Requests and Responses

Much of OpenRosa communication comes in the form of HTTP requests and responses. In
order to properly maintain appropriate formatting and compatibility over time, it is ideal
for some information to be consistently provided on both sides of these interactions.

HTTP Requests

HTTP requests (GET, POST) should contain the following headers:

Header Values Required


Accept- The key for what language a response is ex- No. Response acceptable
Language pected in. in any locale
X-OpenRosa- 1.0 Yes
Version
Date The date on the device in format: Mon, 14 Yes
Feb 2011 16:48:15 GMT

HTTP Requests may additionally specify whether the item count is to be included in the
response envelope. This is done with a query parameter added to the URI.

Arg Values Required


items true|false No. Defaults to false

HTTP Responses

Servers should include the following headers in all responses.

Header Values Required


Content- Two-letter language code (ISO 639-1) No. Recommended for in-
Language ternationalization.
X- 1.0 Yes
OpenRosa-
Version
Date The date on the server in the format: Mon, Yes
14 Feb 2011 16:48:15 GMT

624 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

When a response is issued from an OpenRosa server, the format of the response payload
will often be defined by the specific API (Form List, for instance). However, APIs which
are fundamentally transactional (user registration, form submission, etc) all contain similar
semantics. As such, they will utilize a shared XML Envelope of the format:

<OpenRosaResponse xmlns="http://openrosa.org/http/response" items=""> <!--␣


,→items: Optional number of how many payloads are included in this envelope -->

<message nature=""/> <!--␣


,→0 or 1: message payload to be displayed to the user. Nature is an optional tag␣

,→to group messages by type -->

<!-- PAYLOADS HERE--> ␣


,→ <!-- 0 or many: additional payloads to be parsed per platform-->
</OpenRosaResponse>

For Example:

<OpenRosaResponse xmlns="http://openrosa.org/http/response" items="3">


<message nature="submit_success">Some message to be displayed to the user</
,→message>

<Registration xmlns="http://example.org/user/registration"/> <!-- optional --


,→>

<!--... Some platform specific response ...-->


</OpenRosaResponse>

APIs using this response can then include their namespaced payload inside of the response.
This response should be handled by the client the same way, regardless of the specific sub-
mission. That is, any time an OpenRosa response envelope is received, any of its payloads
should be parsed properly.
Any responses included in the envelope that are unrecognized by the client should be ignored
without error.
Since the server cannot receive confirmation that a response was successfully retrieved, any
responses included in the envelope should be considered idempotent.
The message component of a response envelope should be returned (if possible) in the lan-
guage specified by the Accept-Language header. The nature attribute of a message is an
optional ID which can be used to categorize the type of a response. If the nature of two
messages is identical in a bulk operation, for instance, the assumption is that only one of
them need be presented to a user (presumably the newest).
As an example, if a server submits 4 xforms, and receives the responses

<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message nature="submit_success">Thanks, you've submitted 4 forms today </
,→message>

...
</OpenRosaResponse>

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 625
Chapter 29. OpenRosa

...
<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message nature="submit_success">Thanks, you've submitted 5 forms today </
,→message>

...
</OpenRosaResponse>
...
<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message nature="submit_user_registered">User 'paul' created succesfully!</
,→message>

...
</OpenRosaResponse>
...
<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message nature="submit_success">Thanks, you've submitted 6 forms today</
,→message>

...
</OpenRosaResponse>

A client could present a message like:


Bulk Submit Completed
• Thanks, you’ve submitted 6 forms today
• User ’paul’ created successfully!

29.1.3 Authentication API

This standard specifies the Request and Response format through which OpenRosa compli-
ant servers authorize HTTP transactions.

Overview

This API provides a standard means with which OpenRosa clients are authenticated with
compliant servers.
OpenRosa compliant devices MUST support both:
• the subset of RFC2617 Digest Authentication defined below
• the Basic Authentication mechanism also outlined in RFC2617.
OpenRosa compliant servers MUST support at least one of either:
• the subset of RFC2617 Digest Authentication defined below
• the Basic Authentication mechanism also outlined in RFC2617.

626 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

We are following RFC2617 with additional OpenRosa compliance requirements defined in


the implementation section below to ensure that the Digest Authentication implementations
across devices do not compromise security and that they all implement a well-defined common
subset of the RFC2617 Digest Authentication mechanism.

Data Security Considerations

Any communication over HTTP (vs. HTTPS) can be observed by others and is suscepti-
ble to man-in-the-middle attacks (where a malicious intermediary inserts itself between the
client and the server the client intended to contact). As a consequence, if communication is
over HTTP, clients may be submitting their form data to a malicious intermediary. That
intermediary will see the full contents of the form submission. Additionally, the intermediary
may never forward the submission to the intended server — the client can never be certain
that the submitted data has been recorded on the intended server.
HTTPS requires that the server be configured with an SSL certificate issued by a signing
authority. Man-in-the-middle attacks are possible over HTTPS if clients do not authenticate
the server’s SSL certificate (or, less commonly, if the client device or signing authority has
been compromised).
OpenRosa compliant client devices MUST authenticate server certificates when establishing
HTTPS channels to those servers.
Because client communications are often through unsecured hotspots, it is recommended
that HTTPS (with the authentication of server certificates) be used for all communications.

Typical Interaction

A typical transaction consists of the following steps.


1. The client asks for a resource that requires authentication but does not provide a user
name and password. Typically this is because the user simply entered the address or
followed a link to the page.
2. The server responds with the 401 response code, either requesting Digest Authenti-
cation and providing the authentication realm and a randomly-generated, single-use
value called a nonce, or requesting Basic Authentication (in which case the server
should also redirect and negotiate TLS channel security (https) if the client is not
already communicating over https).
3. At this point, the client will present the authentication realm (typically a description
of the computer or system being accessed) to the user and prompt for a user name and
password. The user may decide to cancel at this point.
4. Once a user name and password have been supplied, the client re-sends the same
request but adds an authentication header that includes the response code.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 627
Chapter 29. OpenRosa

5. Assuming the username and password are valid, the server accepts the authentication
and the page is returned. If the user name is invalid and/or the password is incorrect,
the server might return the 401 response code and the client would prompt the user
again.

Note: A client may already have the required user name and password without needing to
prompt the user; for example, if they have previously been stored by a client.

For Basic Authentication, the ”response” value is simply a base-64 compression of the user
name concatenated with ”:” and the plain-text password, as specified in RFC2617.

Warning: Anyone with a network sniffer could read this value, decompress it, and
obtain the user name and password. Hence, it is critical that this information only be
transmitted over HTTPS or some other secure transport.
Even with HTTPS, sending this is not a highly secure practice.

For Digest Authentication, the ”response” value is calculated in three steps, as follows.
Where values are combined, they are delimited by colon symbols.
1. The MD5 hash of the combined user name, authentication realm and password is
calculated. The result is referred to as HA1.
2. The MD5 hash of the combined method and digest URI is calculated, e.g. of ”GET”
and ”/dir/index.html”. The result is referred to as HA2.
3. The MD5 hash of the combined HA1 result, server nonce (nonce), request counter (nc),
client nonce (cnonce), quality of protection code (qop) and HA2 result is calculated.
The result, the user name and the cnonce are the ”response” value provided by the
client.
The Digest Authentication response value is thus sent in such a way that an adversary can
extract the user name from the response, but cannot extract the password from the response.
It can therefore be sent over an unsecured channel (for example, HTTP ).

Note: Even with the more secure Digest Authentication, HTTPS is recommended.

Implementation

Servers which implement the Authorization API should follow the specifications provided
below in order to be compliant with OpenRosa standards.
• All HTTP interactions MUST be HTTP 1.1

628 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

• Servers MUST conform to RFC2617 for returning one or more authentication schemes
in their 401 challenge. These define the authentication interactions that the server is
willing to accept from the client (for example: Basic, Digest)
• Any server interactions MAY be unauthenticated.
• Non-device (for example, browser) interactions for which the server requires authenti-
cation are NOT required to support Basic or the OpenRosa Restricted Digest authen-
tication scheme. That is, they are allowed to only support Form-based or some other
authentication scheme.
• Device-and-server interactions for which the server requires authentication MUST im-
plement either Basic authentication or the OpenRosa Restricted Digest authentication
scheme as detailed below. The server or device MAY additionally implement other
authentication schemes.
• The device MUST make every effort to proactively supply an Authentication header
line if the requested URI falls within the list of domain URIs covered by a previous au-
thentication interaction. This is to minimize the number of authentication challenges.

Authentication

Clients MUST NOT include authentication credentials in the URL to the server. That is,
this syntax is strictly forbidden:

http://username:password@myhost.org/mypage

Basic Authentication

Basic Authentication MUST NOT be performed over a non-secure (HTTP) connection.


Once the client is aware that basic authentication is required, it SHOULD proactively supply
the basic authentication credentials on every secure request to the server, rather than wait
for the server to reject the request with a 401 response.

OpenRosa Restricted Digest Authentication

This is the Digest Access Authentication Scheme (RFC 2617 Section 3) with the following
restrictions:
• algorithm — server MUST omit or specify ”MD5”
• domain — server MUST specify to help device with proactive inclusion of Authenticate:
header records.
• qop — device MUST support: omitted and ”auth”; server MAY request any of these.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 629
Chapter 29. OpenRosa

• opaque — device MUST return if supplied; server MAY supply this or omit it
• stale — device MUST make every effort to not prompt the user for username and
password if this is TRUE but instead recompute the key with previously cached values
for the username and password.
• cnonce — device SHOULD use a string representation of at least a 48-bit random value
(a random UUID has 126-bit randomness) for the cnonce.

Digest Authentication Security Considerations

Digest Authentication is based upon the MD5 hash algorithm which is now considered too
weak for mainstream cryptographic uses. Digest Authentication remains viable only when
the cnonce and nonce values are random and reasonably long. The use of longer random
strings (e.g., random UUIDs have 126 bits of randomness) is critical for the continued use
of this authentication mechanism.

Digest Authentication Calculations

RFC2069

HA1 = MD5(A1) = MD5(username:realm:password)

HA2 = MD5(A2) = MD5(method:digestURI)

response = MD5(HA1:nonce:HA2)

RFC 2617 (HTTP Authentication: Basic and Digest Access Authentication)

HA1 = MD5(A1) = MD5(username:realm:password)

if qop directive's value is "auth" or unspecified, then HA2 is:

HA2 = MD5(A2) = MD5(method:digestURI)

if qop directive's value is "auth-int" then HA2 is:

HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))

if qop directive's value is "auth" or "auth-int" then compute the response:

response = MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)

if qop directive is unspecified

630 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

response = MD5(HA1:nonce:HA2)

(the above shows that when qop is not specified, the simpler RFC2069 standard is followed)

Digest Authentication Example Interaction

No authentication

Request:

GET /dir/index.html HTTP/1.0

Response:

HTTP/1.0 401 Unauthorized


Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:26:47 GMT
WWW-Authenticate: Digest realm="testrealm@host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
Content-Type: text/html
Content-Length: 311

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">

<HTML>
<HEAD>
<TITLE>Error</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
</HEAD>
<BODY>
<H1>401 Unauthorized.</H1>
</BODY>
</HTML>

Request with username and password

Request (username ”Mufasa”, password ”Circle Of Life”)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 631
Chapter 29. OpenRosa

GET /dir/index.html HTTP/1.0


Host: localhost
Authorization: Digest username="Mufasa",
realm="testrealm@host.com",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"

Response

HTTP/1.0 200 OK
Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:27:03 GMT
Content-Type: text/html
Content-Length: 7984

Example calculation of response using MD5

HA1 = MD5( "Mufasa:testrealm@host.com:Circle Of Life" )


= 939e7578ed9e3c518a452acee763bce9

HA2 = MD5( "GET:/dir/index.html" )


= 39aff3a2bab6126f332b942af96d3366

Response = MD5( "939e7578ed9e3c518a452acee763bce9:\


dcd98b7102dd2f0e8b11d0f600bfb0c093:\
00000001:0a4f113b:auth:\
39aff3a2bab6126f332b942af96d3366" )
= 6629fae49393a05397450978507c4ef1

29.1.4 Form Submission API

This standard defines the API for submitting data to an OpenRosa compliant server and
receiving a response from the server about the submission. This API is designed to pro-
vide a base level of interoperability between OpenRosa clients and servers while enabling
application-specific extensions as well.

Form Submission

OpenRosa servers must be able to receive XForms which are submitted by clients over HTTP.

632 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

There are 3 major categories of requirements for submission which must be fulfilled:
• channel
• content
• correctness.

Channel

OpenRosa servers MUST provide a URI capable of accepting HTTP POST Requests. Access
controls, firewalls and geographic or networking restrictions MAY limit the origins and/or
clients that can access the server.
The server MUST support HTTP 1.1 chunked transfer encoding for receiving the POST
content. There is no minimum set of standards for timeouts, maximum content length, or
other http configurations, but servers are encouraged to support lenient connections and the
largest possible content size, since many of the connections will be from unreliable channels
and in environments where splitting content up is impractical.
For maximum compatibility with J2ME clients, it is recommended that a server SHOULD
NOT issue redirects.

Note: Using digest authentication and https when communicating with a server does not
require any redirects — you can have authentication and secure transport without redirects.

Content

OpenRosa submissions (and responses) MUST provide headers conforming to the OpenRosa
Request standard.
Successful server responses MUST include an X-OpenRosa-Accept-Content-Length
header in addition to the required OpenRosa Request response headers. The
X-OpenRosa-Accept-Content-Length header specifies this server’s recommended maximum
size for a POST body, in bytes.
Servers SHOULD include this header in their error responses. However, clients MUST NOT
rely on the presence of this header (or any OpenRosa header) in every error response.

Note: Overly-large requests sent to Google App Engine will be rejected prior to being sent
to any server, and will therefore not contain this (or any) OpenRosa header.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 633
Chapter 29. OpenRosa

OpenRosa submissions are POSTed to servers as a multipart MIME Envelope with at least
1 part — the XML content of the form itself. Each of these parts should adhere to the
following requirements

MIME Envelope

• Content Type: multipart/form-data


• Contains Exactly 1 XForm Part
• Contains 0 or More Additional Parts

XForm Part

• Content Type: text/xml


• Name: xml_submission_file

Additional Parts

• Content Type: arbitrary


• Name: matches an appropriate element inside of the XForm Element’s XML.
Servers MAY be more permissive than this specification (for example, allowing multi-
part/mixed for the mime envelope), but MUST be capable of recognizing and properly
receiving submissions in this format.

Correctness

The server MUST consume an entire HTTP POST in conformance with that protocol. Once
a POST is received, the range and structure of the server’s response is specified below.

Extended Transmission Considerations

If the client is capable of negotiating authenticated and/or secure transmissions to the server,
it is recommended that the client first attempt a HEAD request to the server to negotiate
the authentication and channel security prior to the first POST of the data, regardless of
any channel security stated in the <submission> element of the form. This ensures that
submitted data is not inadvertently sent in the clear on that first request due to the client
device possessing an out-of-date form definition with inaccurate <submission> content.

634 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

Issuing a HEAD request first also reduces overall transmission bandwidth in instances where
client authentication occurs. Most authentication handshake protocols require the complete
re-POST of the original request after the authentication is complete. By delaying the POST
of the data until after the authentication has been negotiated on the HEAD request, overall
transmission bandwidth is reduced.
The client, upon receiving the HEAD response, can check that the response contains the
X-OpenRosa-Version header to indicate that the host is an OpenRosa server (as op-
posed to a network login screen or proxy page). In this way, the server can change
the scheme from http to https or update the submission page URL without a wasted
redirect during the actual submission process. The client can also use the value of the
X-OpenRosa-Accept-Content-Length header to inform itself of how big a POST body
should be sent to this server. ODK Collect also requires a 204 (No Content) status code in
the HEAD response.
If a full POST of the form’s XML submission and its additional parts (for exam-
ple, captured image, audio or video clips) would exceed the size specified in the
X-OpenRosa-Accept-Content-Length header (the maxSize), it is recommended that the
client split the POST into multiple individual POST requests, each containing the form’s XML
submission and one or more additional parts such that each partial POST request is no greater
than maxSize; if a single additional part is greater than maxSize, the POST should contain
the form’s XML submission and that single additional part. Regardless of whether the client
observes and honors the X-OpenRosa-Accept-Content-Length header, a compliant server
with give its best effort to accept submissions of any length.
The X-OpenRosa-Accept-Content-Length header is provided to avoid failures that may
otherwise arise due to restrictions on the overall size of HTTP messages, or due to physical or
virtual memory configurations of the server.
The form’s XML submission is sent on each POST so that a client can avoid having any
knowledge about the content of the files it is shipping around. Doing so also places the
fewest restrictions on how the server handles the submission.

Rationale for sending the form’s XML submission

To avoid sending the form’s XML submission, you would need to inspect the submission
and send up its identifying information. By avoiding inspection of the submission, a much
simpler Ajax-enabled webpage could conform to this API.
On the server, having just the instanceID sent on subsequent POST requests might not be
sufficient to process the request — sending only this information would burden those server
implementations with maintaining a mapping from the instanceID to the natural key for this
data. Not sending the form’s XML submission in subsequent POSTs biases against some
server designs.
Finally, since most XML submission documents are smaller than 2K bytes, and if you have
a 10M byte threshold for splitting a submission across multiple requests (a reasonable lower

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 635
Chapter 29. OpenRosa

limit), you’re burning only 0.02% of your bandwidth with the retransmission.

Server Response Format

The server response format will be XML formatted, and the response body will be an Open-
Rosa Response.
Example response:

<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message>Form Received! You've submitted 5 forms today</message>
</OpenRosaResponse>

If the server is RESTful, the server MAY return an HTTP URI (using the standard HTTP
Location header) where the form can be found.
A form should not be assumed to be submitted until a 201 or 202 response code is received
with an OpenRosaResponse envelope body.

Server Status Codes

Server status codes will be the same as standard http codes. These use the general classifi-
cation:
201-202 Successfully received by server.
4XX Client Error
5XX Server Error

Note: 1XX (informational) and 3XX (redirection) probably do not apply to these POSTs.

Some common interpretations of codes are below, but more could apply.

636 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

Code HTTP ODK Meaning


Mean-
ing
200 UN- Since the request is a post, a 200 response is not a sign of a successful
USED submission. Many intermediate proxies will return a 200 response for gate-
way pages on WI-FI, etc, so receiving a 200 shouldn’t be assumed to be
meaningful.
201 Form Everything went great. Thanks for submitting.
Re-
ceived
202 Ac- We got and saved your data, but may not have fully processed it. You
cepted should not try to resubmit.
204 No Status returned in response to a HEAD request.
Con-
tent
401 Unau- Client tried to post something it didn’t have permission to post.
tho-
rized
403 For- You’re not allowed to post to this server.
bidden
404 Not Unknown URI endpoint, domain, or other
Found
413 Re- The request body is too large for the server to process
quest
too
large
500 Inter- Something went awry on the server and we’re not sure what it was
nal
Server
Error

29.1.5 Form List API

This standard specifies how clients discover a list of available blank forms on a server.

Discovery Request

The discovery request should be sent in compliance with the HTTP 1.1 protocol.
If a server will filter the set of forms based upon the user’s identity, then the server should
require that the user be authenticated through either the Authentication API or through an

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 637
Chapter 29. OpenRosa

alternative authentication mechanism. The server can then make use of the user’s authen-
ticated identity through those mechanisms to filter the set of forms to be returned.
The device will make a discovery request to a configured URI with a single query parameter,
the deviceID. The deviceID should be the same id as provided by the default population
mechanism defined in the Metadata Scheme. The server may filter the set of forms returned
using this information.

Warning: The deviceID is advisory information only, and is inherently not authori-
tative. Anyone can claim to have a given IMEI, for example.

Together, the authentication and deviceID enable a server to tailor the set of forms to both
the user and the device (and therefore the device’s capabilities).

Query Parameters

Optional query parameters MAY also be supplied:


• formID If specified, the server MUST return information for only this formID.
• verbose If specified with the value true, the server MAY include a <descriptionText/
> or <descriptionUrl> element providing a longer description of an XForm.
• listAllVersions If specified, provides a listing of all hosted versions of each form
(including the <version> element) in the response document (see below).
If not supplied or not present, the server MUST NOT include this optional information in
its response.

Request Header

Requests from the device SHOULD set the Accept-Language header to indicate the preferred
language of the form name

Read More
The Accept-Language HTTP header is documented here:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
and an article on its evolving use for determining locale is here:
http://www.w3.org/International/questions/qa-accept-lang-locales

638 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

Aside from the query parameters, the structure of the server URI and whether the request
is made over http or https, is entirely implementer- and server- dependent.
Compliant servers MUST NOT require additional query parameters on this request.
Compliant devices MUST be able to handle arbitrary http and https URIs and must be
able to authenticate with the server during this transaction, if required by the server.

Successful Response Document

If accepted by the server, the server will respond with a Content-Type: text/xml;
charset=utf-8 response. An example of such a document is shown below:

<?xml version='1.0' encoding='UTF-8' ?>


<xforms xmlns="http://openrosa.org/xforms/xformsList">
<xform>
<formID>mydomain.org:formId</formID>
<name>Form with zero or more additional files</name>
<version>1.1</version>
<hash>md5:c28fc778a9291672badee04ac880a05d</hash>
<descriptionText>A possibly very long description of the form</
,→descriptionText>

<downloadUrl>http://myhost.com/app/path/getMe/formIdA</downloadUrl>
<manifestUrl>http://myothehost.com/app/path/getOtherStuff?formId=formIdA</
,→manifestUrl>

</xform>
<xform>
<formID>http://mydomain.org/uniqueFormXmlns</formID>
<name>Form without additional files</name>
<version>v50 alpha</version>
<hash>md5:c28fc778a9291672badee04ac770a05d</hash>
<descriptionUrl>http://mysecondhost.com/a/description/getMe@formId=uniqueKey
,→</descriptionUrl>

<downloadUrl>http://mysecondhost.com/a/different/path/getMe@formId=uniqueKey
,→</downloadUrl>

</xform>
<xforms-group>
<groupID>someId</groupID>
<name>Short name of grouping</name>
<listUrl>http://whateverhost.com/other/path/forDownload?group=fido</listUrl>
<descriptionText>Longer description of what is here</descriptionText>
<descriptionUrl>http://morehost.com/description/link</descriptionUrl>
</xforms-group>
</xforms>

This document consists of:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 639
Chapter 29. OpenRosa

• a top-level <xforms/> element in the http://openrosa.org/xforms/xformsList


namespace enclosing,
– zero or more <xform/> tags followed by
– zero or more <xforms-group> tags.
Within each of the <xform/> tags, there must be exactly one of each of the following:
• <formID/>
• <name/>
• <version/>
• <hash/>
• <downloadUrl/>
There may be zero or one
• <descriptionText/>
• <descriptionUrl/>
• <manifestUrl/>
Within each <xforms-group> tag, there must be exactly one of each of the following:
• <groupID/>
• <name/>
• <listUrl/>
There may be zero or one
• <descriptionText/>
• <descriptionUrl/>
The <xform/> tag provides information about a single form. The <xforms-group/> tag
provides information about a group of forms; a further enumeration of the forms within that
group can be obtained through the <listUrl/> of that group (which returns an <xforms/>
document). Groups can be used to define sets of forms that a user may wish to download
together (such as for clinical studies, for example).

Elements within <xform/>

• <formID/> The form identity as defined in the metadata.


• <name/> The user-friendly display name of the form. The server may localize this name
(translate it) based upon the Accept-Language: header on the incoming request.
Devices SHOULD send this header and servers MAY return different name and

640 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

description text based upon its value. The default behavior is to return the text
within the <title> element of the XForm.
• <version/> The form version as defined in the metadata The device MAY use this to
determine if its XForm definition is out of sync with the server (over time, the server
may roll the current version forward or backward).
• <hash/> The hash value of the form definition file available for download. The only
hash values currently supported are MD5 hashes of the file contents; they are prefixed
by md5:. If the hash value identified in the form list differs from the hash value for a
previously-downloaded form definition file, then the file should be re-fetched from the
server.
• <downloadUrl/> A fully formed URI for downloading the form to the device. It may
be a valid http or https URI of any structure; the server may require authentication;
the server may require a secure (https) channel, etc.
• <manifestUrl/> A URI from which the device can obtain a manifest defining addi-
tional supporting objects and files. Optional
• <descriptionText/> A detailed text explanation of the form. Optional, only returned
if verbose=true.
• <descriptionUrl/> A fully qualified URI pointing to a media (audio, video) descrip-
tion of the form. Optional, only returned if verbose=true.

Tip: A media description of the form (audio or video) can be especially useful in low-literacy
populations.

Elements within <xforms-group/>

• <groupID/> The unique id for this group. It is locale-invariant (in contrast to the
<name/> element, below).
• <name/> The user-friendly display name of the xforms group. The server may localize
this name (translate it) based upon the Accept-Language: header on the incoming
request. Devices SHOULD send this header and servers MAY return different name
and description text based upon its value.
• <listUrl/> A fully qualified URI for obtaining the <xforms/> document of this group-
ing of forms. (That is, the endpoint for the Form List API). It may be a valid http
or https URI of any structure; the server may require authentication; the server may
require a secure (https) channel, etc.
• <descriptionText/> A detailed text explanation of the form group. Optional, only
returned if verbose=true.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 641
Chapter 29. OpenRosa

• <descriptionUrl/> A fully qualified URI pointing to a media (audio, video) descrip-


tion of the form group. Optional, only returned if verbose=true.

Note:
• The server MAY dynamically construct the download and manifest URLs based upon
the user identity and device id.
• The manifest MAY include additional (implementation specific) elements and data.
These MUST be dealt with gracefully (ignored) by the client if it does not know how
to interpret these fields.

The Manifest Document

The structure of the manifest document returned by the manifest URI is as follows:

<?xml version='1.0' encoding='UTF-8' ?>


<manifest xmlns="http://openrosa.org/xforms/xformsManifest">
<mediaFile>
<filename>badger.png</filename>
<hash>md5:c28fc778a9291672baddd04ac880a05d</hash>
<downloadUrl>http://funk.appspot.com/binaryData?blobKey=%3A477e3</downloadUrl>
</mediaFile>
<mediaFile>
<filename>path/to/agilefrog.png</filename>
<hash>md5:9fd39ac868eccdc0c134b3b7a6a25eb7</hash>
<downloadUrl>http://other.appspot.com/blobSource?foo=222</downloadUrl>
</mediaFile>
</manifest>

This document consists of:


• a top-level <manifest/> tag in the http://openrosa.org/xforms/xformsManifest
namespace enclosing
– zero or more <mediaFile/> tags.
– Within each of the <mediaFile/> tags, there must be exactly one of each of the
following:
* <filename/>
* <hash/>
* <downloadUrl/>

642 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
29.1. OpenRosa 1.0 APIs

Elements within <mediaFile/>

• <filename/> The unique un-rooted file path for this media file. This un-rooted path
must not start with a drive name or slash and must not contain relative path naviga-
tions (for example, . or ..).
• <hash/> The hash value of the media file available for download. The only hash values
currently supported are MD5 hashes of the file contents; they are prefixed by md5:. If
the hash value identified in the manifest differs from the hash value for a previously-
downloaded media file, then the file should be re-fetched from the server.
• <downloadUrl/> A fully qualified URI for downloading the media file to the device.
It may be a valid http or https URI of any structure; the server may require authen-
tication; the server may require a secure (https) channel, etc.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 643
Chapter 29. OpenRosa

644 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTY

ODK JAVAROSA

JavaRosa is a Java library for rendering forms that are compliant with ODK XForms spec.
It is the heart of many of the ODK tools. ODK JavaRosa is a fork of JavaRosa 1.0 that has
been modified to NOT run on J2ME devices. The key differences are:
• Regularly updated to ensure spec compliance
• KoBo additional instance defn. and filter paths
• Remember all bind attributes and any additional attributes on <input>, <select>,
<group>, etc. statements
• Numerous enhancements and contributions from SurveyCTO and others
• J2ME sub-projects removed

30.1 Architecture

30.2 Integration Points

This section describes how the different parts of ODK use JavaRosa.

30.2.1 Aggregate

30.2.2 Briefcase

30.2.3 Collect

30.2.4 Validate

Two source files in Validate use JavaRosa.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 645
Chapter 30. ODK JavaRosa

FormValidator.java

core/model/Constants.java
core/model/FormDef.java
core/model/FormIndex.java
core/model/GroupDef.java
core/model/IFormElement.java
core/model/SelectChoice.java
core/model/condition/EvaluationContext.java
core/model/condition/IFunctionHandler.java
core/model/data/IAnswerData.java
core/model/instance/InstanceInitializationFactory.java
core/model/instance/InvalidReferenceException.java
core/model/instance/TreeElement.java
core/model/instance/TreeReference.java
core/model/utils/IPreloadHandler.java
core/model/utils/QuestionPreloader.java
core/services/PropertyManager.java
core/services/PrototypeManager.java
form/api/FormEntryCaption.java
form/api/FormEntryController.java
form/api/FormEntryModel.java
form/api/FormEntryPrompt.java
model/xform/XFormsModule.java
xform/parse/XFormParseException.java
xform/util/XFormUtils.java

StubPropertyManager.java

core/services/properties/IPropertyRules.java
core/services/IPropertyManager.java

646 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTYONE

LAUNCHING ODK COLLECT FROM EXTERNAL APPS

See also:
Launching External Apps
ODK Collect supports several intents which allow it to be launched by external applications.
You can open a specific form or lists of empty forms, saved forms, finalized forms or sent
forms.
This section describes how to launch ODK Collect and open its activities from an external
app. The code samples go in your custom Android application.

31.1 Understanding Intents

An Intent is a messaging object you can use to request an action from another app component.
For more details on intents, you can refer to these Android docs.

31.2 Launching Collect activities from external application

To start one of ODK Collect’s activities:


1. Create a new intent using an appropriate action.
2. Set the type of the created intent.
3. Start an activity using the intent.

31.2.1 Launching the form list or instance list activity

Intent intent = new Intent(Intent.ACTION_VIEW);


intent.setType("vnd.android.cursor.dir/vnd.odk.form");
startActivity(intent);

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 647
Chapter 31. Launching ODK Collect from External Apps

This displays a list of forms and allows the user to select one and fill it.
Similarly for an instance of the form:

Intent intent = new Intent(Intent.ACTION_VIEW);


intent.setType("vnd.android.cursor.dir/vnd.odk.instance");
startActivity(intent);

This displays a list of saved forms and allows the user to select one and edit it.

31.2.2 Getting the URI of a form or instance chosen by the user

Intent intent = new Intent(Intent.ACTION_PICK);


intent.setType("vnd.android.cursor.dir/vnd.odk.form");

static final int PICK_FORM_REQUEST = 1; // The request code


startActivityForResult(intent, PICK_FORM_REQUEST);

To get the result, override onActivityResultMethod in the following way:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == PICK_FORM_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The Intent's data URI identifies which form was selected.
Uri formUri = data.getData();
// Do something with the form here
}
}
}

For an instance, change the intent type:

intent.setType("vnd.android.cursor.dir/vnd.odk.instance");

31.2.3 Using a URI to edit a form or instance

If the URI of a form or instance is known, it can be viewed or edited. For example, a URI
received in onActivityResult() as described above can be used.

648 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
31.2. Launching Collect activities from external application

Intent intent = new Intent(Intent.ACTION_EDIT);


intent.setData("content://org.odk.collect.android.provider.odk.forms/forms/2");
startActivity(intent);

The same thing can be done with a specific instance.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 649
Chapter 31. Launching ODK Collect from External Apps

650 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTYTWO

BRIEFCASE AGGREGATE API

32.1 Introduction

This describes the interfaces ODK Briefcase uses when interacting with ODK Aggregate
v1.0.
In general, the server should adhere to the OpenRosa API described here.

32.2 Pull

Interfaces used during Pull actions.


The APIs used:
1. OpenRosa Form Discovery API
2. Download forms and media files using URLs form discovery.
3. view/submissionList to obtain a chunk of submission keys.
4. view/downloadSubmission to download an individual submission.

32.3 Push

Interfaces used during Push actions.


1. formUpload to upload a form and its media files to ODK Aggregate.
2. view/submissionList to obtain a chunk of submission keys.
3. OpenRosa Form Submission/Overwrite API (with extensions)

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 651
Chapter 32. Briefcase Aggregate API

32.4 Interface Details

32.4.1 OpenRosa Form Discovery API

Vanilla conformance.

32.4.2 OpenRosa Form Submission/Overwrite API

Server Processing

The server does special processing to look for an instanceID or a submissionDate attribute
on the top-level element of the submission.
If the OpenRosa Metadata block is not present, it uses the instanceID attribute value as the
instance ID for this submission.
If the submissionDate is present, it uses that value as the submission date for this submission
(rather than the current datetime). SubmissionDate should be in ISO8601 format.

Response

The response from the server looks like:

<OpenRosaResponse xmlns="http://openrosa.org/http/response">
<message>...</message>
<submissionMetadata xmlns="http://www.getodk.org/xforms"
id="formid" version="..." encrypted="yes" instanceID="..."
submissionDate="..."
isComplete="true" markedAsCompleteDate="..."/>

The <submissionMetadata/> tag contains all the metadata for this submission that the
server has assigned it.
The form id and version are given (version is omitted if null).
If the form is an encrypted form, the encrypted attribute is present, otherwise it is omitted.
If present, it has a value of yes (vs. true).
The instanceID is either the server-assigned instance id or the instanceID from the Open-
Rosa Metadata block.
The submissionDate is the date of first submission of this record on the server.
The isComplete flag is true if the server has all attachments associated with this filled-in
form. Otherwise, it will be false. If it is true, the markedAsCompleteDate will be the date
when the submission became complete.

652 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
32.4. Interface Details

The date fields are formatted using:


import org.javarosa.core.model.utils.DateUtils;

DateUtils.formatDateTime(d, DateUtils.FORMAT_ISO8601)

The only 2 fields ODK Briefcase currently uses are the instanceID and submissionDate
fields. It may eventually use the isComplete flag.

Briefcase Treatment

After a submission has been pushed to the server, it updates the top-level element, inserting
the instanceID and submissionDate fields if they are not already present.
If they are present, it compares the fields and warns if there is any discrepancy between
them.

32.4.3 Download forms and media files

It is same as the API ODK Collect uses.


ODK Briefcase downloads the forms so that it has the form model available for CSV exports
and to ensure that a push uses matching form definitions.

32.4.4 formUpload

This is FormUploadServlet in ODK Aggregate.


It is a multipart POST. The POST always contains the form definition file, and has as many
media files as would fit in under 10MB. This follows the behavior of the OpenRosa Form
Submission/Overwrite API.
Because of the limitations of HTML file input tags, all media files must be in a single folder
(no sub-directories). The server assumes this is the case.
Here is a sample web page fragment to post to this servlet:
<form id="ie_backward_compatible_form" action="/formUpload"
enctype="multipart/form-data" encoding="multipart/form-data"
method="POST" accept-charset="UTF-8">
<table id="uploadTable">
<tbody>
<tr>
<td>
<label for="form_def_file">Form definition (xml file):</label>
</td>

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 653
Chapter 32. Briefcase Aggregate API

<td>
<input id="form_def_file" class="gwt-Button" type="file"
name="form_def_file" size="80">
</td>
</tr>
<tr>
<td>
<label for="mediaFiles">Optional Media file(s):</label>
</td>
<td>
<input id="mediaFiles" class="gwt-Button" type="file"
multiple="" name="datafile" size="80,20">
<input id="clear_media_files" class="gwt-Button"
type="button"
onclick="clearMediaInputField('mediaFiles')"
value="Clear">
</td>
</tr>
<tr>
<td>
<input class="gwt-Button" type="submit"
value="Upload Form" name="button">
</td>
</tr>
</tbody>
</table>
</form>

32.4.5 GET view/submissionList

Download the list of completed submissions for a given form. Incomplete or partial submis-
sions must not be returned. You may wish to report only approved submissions if you have
a QA review step.
There are 3 query arguments:
1. formId – identifies the form. Just the id from the form definition (e.g., geo_tagger_v2).
2. cursor – an opaque string used by the server to as a query resume point. Omit on the
first call.
3. numEntries – the number of entries to return.

Returned Document

The returned XML document is of the form:

654 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
32.4. Interface Details

<idChunk xmlns="http://getodk.org/submissions">
<idList>
<id>uuid:e5aa4247-cfb8-4cc5-87cd-52fbfe491b13</id>
<id>uuid:8ca4433a-fed2-4d1c-b333-c0378203f68f</id>
</idList>
<resumptionCursor>opaquedata</resumptionCursor>
</idChunk>

Where the idList contains a series of id elements containing strings that can be used to
construct the needed string to pass to the view/downloadSubmission API.
The resumptionCursor holds opaque data that is used by the server to track the location
at which to resume the list of ids.

ODK Briefcase Treatment

ODK Briefcase repeatedly calls this API, passing in the previous response’s
resumptionCursor value until the returned resumptionCursor value matches that given
in the request. Once it no longer changes, ODK Briefcase assumes that all id data has been
downloaded from the server.

32.4.6 GET view/downloadSubmission

Download an individual submission.


One Query argument: formId – a multipart XPath-like string query that identifies the
individual submission.
The formId is a string of the form:

formid[@version=null and @uiVersion=null]/topElement[@key=idvalue]

• formid is the form id, as would be provided to the submissionList API.


• version is either null if not used or the version number of the form (ODK Aggregate
only supports integer version strings at this time).
• topElement is the name of the top-level element in the submission. This is the element
nested just within the <instance> element of the <model> (it also has the id attribute,
which should be equal to the formid).
• idvalue is the value of the individual submission id returned by the view/
submissionList API, usually a UUID.
An example, where no version was attached to the form definition uploaded to Aggregate:

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 655
Chapter 32. Briefcase Aggregate API

GET /view/downloadSubmission?formId=my_odk_form[@version=null and␣


,→@uiVersion=null]/data[@key=uuid:38fd4ef4-28b9-441e-a818-dd8cbe514b2c]

While it is desirable for the idvalue to be the instanceID of the submission, it is not
required. For ODK Aggregate v1.x, it will be the instance ID; for ODK Aggregate 0.9.x, it
is not the instance ID.

Note: formid may be a URL (since it might be an xmlns), so when parsing this query
parameter, it is safest to find the last instance of @version and split the string at that
location. In any case, it is your string to parse and interpret for your server configuration.

Response Document

The response is of the form:

<submission xmlns="http://getodk.org/submissions"
xmlns:orx="http://openrosa.org/xforms" >
<data>
...reconstructed submission XML...
</data>
<mediaFile>
<fileName>...</fileName>
<hash>md5:...</hash>
<downloadUrl>...</downloadUrl>
</mediaFile>
...repeat as needed...
</submission>

The <mediaFile> tag has the same interpretation as it does in the OpenRosa Form Listing
API’s manifest XML.
The reconstructed submission XML generally does not respect the namespaces of the original
form definition. As a special case, if it finds a form group that could be interpreted as the
OpenRosa Metadata block, it does use the orx namespace for that.
Like the <submissionMetadata> tag on the Form Submission/Overwrite API response, the
top-level element in the submission XML contains all the metadata fields supplied by the
server.

656 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTYTHREE

ENCRYPTED FORMS

33.1 Overview

Encrypted forms provide a mechanism to keep your data private even when using http:
for communications (for example, when you do not have an SSL certificate or https: is
not available). Encrypted forms may also enable Google App Engine deployments (and
deployments using other web database services, such as, AWS) to comply with data privacy
laws, eliminating the necessity for setting up your own servers to meet those requirements.
Encrypted forms apply asymmetric public key encryption at the time the form is finalized
within ODK Collect. This encrypted form can then be submitted to a server. ODK Cen-
tral provides a managed encryption option <central-encryption> which means a decrypted
data file can securely be downloaded without using any other tool. Central self-managed
encryption and other servers require using ODK Briefcase to download and decrypt the data.
Briefcase, when supplied with the asymmetric private key (which Briefcase never stores), can
then decrypt and export the form data as a CSV file for your use.
The finalized form’s data (and media attachments) are encrypted before being submitted to
a server and remain encrypted while stored on the server. When using Briefcase, the data
remains encrypted as it is pulled, where it is again stored in encrypted form.

Note:
• A server cannot present or share the data with another service since the encryption
obscures the entire contents of the form and the server never possesses the asymmetric
key required to decrypt the form.
• When using encrypted forms, the server serves only as a data aggregation point.

The non-encrypted data is available on the ODK Collect device during data collection and
whenever a form is saved without marking it as complete. Once you mark a form as complete
(finalize it), Collect will generate a random 256-bit symmetric key, encrypt the form contents
and all attachments with this key, then construct a submission manifest which describes the
encrypted submission and an asymmetric-key encryption of the symmetric key used for the

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 657
Chapter 33. Encrypted Forms

encryption. This manifest is the ”form” that is uploaded to a server, with the encrypted
form contents and its encrypted attachments appearing as attachments to this submission
manifest ”form.”

33.2 Requirements

Encrypted forms require the following minimum versions of the ODK tools
• ODK Collect 1.2 Release Candidate 1 (RC1) or higher
• ODK Aggregate 1.0.4 Production or higher
• ODK Briefcase 1.0 Production or higher

Warning: Encrypted form definitions must include a unique OpenRosa instanceID and
have an explicit <submission/> element

These requirements are covered in more detail below.

33.3 Security Concerns

While ODK Collect attempts to remove all unencrypted copies of a finalized form and its
attachments from the device, because ODK Collect uses third-party applications for image
capture, etc., and because of the potential for Forced Close events during the clean-up
process, we cannot guarantee that all copies will have been destroyed. Furthermore, because
of the way an SD card writes and deletes information, there is a possibility of this data being
recoverable from the free space on the SD card. Your organization should investigate the
extra steps needed to ensure all data is deleted from the SD cards on your ODK Collect
devices and should establish procedures to periodically wipe and reinstall those devices.

Note: Encrypting a form ensures that the finalized form is not readable and is not tam-
pered with. However, there is nothing preventing a malicious adversary from the wholesale
replacement of a finalized form with falsified data or the synthesis and submission of extra
data — these are not contingencies that encrypted forms seek to address.

658 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
33.4. Configuration

33.4 Configuration

For ODK Briefcase, you must use Java 8.0.221 or higher. We recommend installing OpenJDK
11 LTS from AdoptOpenJDK.

33.4.1 Windows

The JRE is usually installed here:


C:\Program Files\Java\jre1.x.x_xxx\lib\security
You might also have a JDK. If you do, you must also install the JCE files there:
C:\Program Files\Java\jdk1.x.x_xxx\jre\lib\security

33.4.2 macOS

The JRE is usually found here:


/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/
security
You might also have a JDK. If you do, you must also install the JCE files there:
/Library/Java/JavaVirtualMachines/jdk1.x.x_xxx.jdk/Contents/Home/jre/lib/
security

33.5 Uploading Finalized Forms

<h:html xmlns="http://www.w3.org/2002/xforms"
xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:orx="http://openrosa.org/xforms/">
<h:head>
<h:title>Sample Form</h:title>
<model>
<itext>
<translation lang="English" default="">
<text id="ask_name">
<value form="long">Please enter your name:</value>
<value form="short">Respondent's name</value>
</text>
</translation>
</itext>
<instance>

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 659
Chapter 33. Encrypted Forms

<sample id="sample-v1.0">
<orx:meta>
<orx:instanceID/>
</orx:meta>
<name/>
</sample>
</instance>
<submission method="form-data-post"
action="https://my-opendatakit.appspot.com/submission"
base64RsaPublicKey="MIIBIjANB...JCwIDAQAB" />
<bind nodeset="/sample/meta/instanceID" type="string" readonly="true()"
calculate="concat('uuid:', uuid())"/>
<bind nodeset="/sample/name" type="string" />
</model>
</h:head>
<h:body>
<input ref="name">
<label ref="jr:itext('ask_name')"/>
</input>
</h:body>
</h:html>

If you are using XLSForm, then form encryption is governed by the settings on the Settings
Worksheet. Encrypted forms must specify a submission_url and a public_key on this work-
sheet. If both are specified, XLSForm will generate an encrypted-form definition. Skip to
the following sections to see how to create a public-private key pair and specify the public
key.
The required element to make this form an encrypted form is the <submission/> tag. Within
this tag, the method attribute should always be form-data-post. The action attribute
should be the url to which the submission should be posted. For Central, this is the server
URL configured in Collect for the App User followed by /submission. For Aggregate, this is
the url with Aggregate.html replaced by submission. Finally, what identifies the form as an
encrypted form is the presence of a base64RsaPublicKey attribute. This should be the base64
encoding of the RSA public key that Collect uses to encrypt the symmetric encryption key
it creates to encrypt a finalized instance of this form (a different symmetric encryption key
is created for every finalized form)

33.6 Creating RSA Key pair

RSA public-private key pairs are generated using the OpenSSL software package. This is
pre-installed on macOS and Linux but needs to be downloaded and installed on Windows.

660 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
33.6. Creating RSA Key pair

33.6.1 Install OpenSSL (Windows only)

For Windows, download and run the OpenSSL installer appropriate for your system from
OpenSSL for Windows. When it asks whether to copy the DLLs to the Windows system
directory or to the /bin directory, choose the /bin directory (either will work, but this will
minimize the pollution of the Windows system directory)

33.6.2 Constructing the RSA Key Pair

If you are on Windows, open a PowerShell or command prompt window. Change directories
to the /bin directory in the OpenSSL directory.

> cd C:\OpenSSL-Win32\bin

If you are on a Mac, open the terminal. Change directories to your Desktop.

$ cd ~/Desktop

33.6.3 Create a private key

The following command will create a 2048-bit private key and write it to the MyPrivateKey.
pem file. This may complain about a missing configuration file. You can ignore this warning.
If you are on Windows, run:

> openssl genpkey -out MyPrivateKey.pem -outform PEM -algorithm RSA -pkeyopt rsa_
,→keygen_bits:2048

Warning: On Powershell
Check $env:path to be sure path\OpenSSL-Win64\bin is in there.If it is not,
run the following command in Powershell:
> $env:path = $env:path + ";path to OpenSSL-Win64\bin"

If you are on a Mac, run:

$ openssl genrsa -out MyPrivateKey.pem 2048

33.6.4 Extract a public key

Next, you need to extract the public key for this private key.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 661
Chapter 33. Encrypted Forms

Run the following command:

openssl rsa -in MyPrivateKey.pem -inform PEM -out MyPublicKey.pem -outform PEM -
,→pubout

This may also complain about a missing configuration file. You can ignore this warning.

33.6.5 Storing and using the keys

Move the MyPrivateKey.pem file to a secure location. It does not have a password encoding
it, so anyone can decrypt your data if they have access to this file. This is the private key
file that you will give to ODK Briefcase when decrypting the data.

33.6.6 Updating the public_key field in the XLSForm settings work-


sheet.

Open the MyPublicKey.pem file and copy the resulting very-long string inside —-
BEGIN/END—- lines and paste it into the public_key field in the XLSForm settings
worksheet. This very-long string will become the base64RsaPublicKey attribute in the re-
sulting encrypted form definition.

Note:
• You need to be especially careful that this is ONLY the public key and not the contents
of the original public-private key file (which would also appear to work but provide no
security).

Tip:
• You can use Notepad (Windows) or TextEdit (Mac) to open MyPublicKey.pem
• Alternatively, you can use the command less MyPublicKey.pem to print the contents
into the terminal and directly copy/paste from there.

See also:
• For reference, you can checkout the tutorial encrypted-XLSForm.It is for viewing pur-
pose only but you can make your own copy to edit it.

662 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
33.7. Operations

33.7 Operations

Operationally, you would add the form definition to the server identified in the <submission>
tag’s action attribute, and deploy everything using Collect, figure out how you want to im-
plement a periodic SD Card wiping protocol for your devices, and you’re done. Submissions
will be encrypted when marked as complete. Once the data is on your server, use Briefcase to
download the encrypted submissions to your desktop computer, and then specify the private
key PEM file when decrypting and generating the CSV files.

Note:
• ODK Central or ODK Aggregate will only hold the encrypted submission with no
access to the private key
• ODK Briefcase will emit the CSV with an extra final column that indicates whether
the signature of the encrypted file was good or bad. It would be bad if any of the at-
tachments are missing or if there was tampering (other than the wholesale replacement
of a submission, which can’t be detected).

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 663
Chapter 33. Encrypted Forms

664 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTYFOUR

SECURITY AND PRIVACY

This document details known security and privacy considerations of the ODK software.

• License
• Communication Channels
• 3rd-party Software
• Websites
• Google Play Store
• ODK Aggregate
– Communications
– Google App Engine and other Hosting Services
– Username Authentication
• ODK Briefcase
• ODK Build
• ODK Collect
• XLSForm Online
• Cross-tool Concerns
– Encrypted Form Security
– Identifying Information Transmission and Storage

34.1 License

The ODK software is released under the Apache 2 License.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 665
Chapter 34. Security and Privacy

All other artifacts (for example, the ODK website and this documentation) are released
under the Creative Commons Attribution 4.0 International License.
All our installers, programs, source code, and documentation are provided AS-IS with no
warranty or conditions, and without any liability obligations. See the license text for details.

34.2 Communication Channels

Outside of usage analytics (typically opt-out) and crash reports (typically required), ODK
software does not transmit or communicate any information (e.g., survey data) back to
ODK’s maintainers. When we do gather data, we default to anonymous or aggregate meth-
ods.
The software we have written does not have any mechanisms that might allow us to access
or control your devices or systems.
There is always the possibility that hackers can discover and exploit deficiencies or bugs in
our software or in 3rd-party libraries to access or control your devices or systems.

34.3 3rd-party Software

Our software uses a number of open-source 3rd-party libraries from well-known and/or rep-
utable sources, and a few from obscure sources. We do not vet the security of those software
libraries.
Your security staff may want to review the libraries and source code on GitHub.

34.4 Websites

Our websites under the getodk.org domain use cookies and log all interactions. We also use
web analytics tools (for example, Google Analytics) that may track visitors and their access
patterns on our web properties.

34.5 Google Play Store

Downloads from the Google Play Store are compiled into aggregated usage statistics.
Crash reports you elect to send are provided to us anonymously. By design, these do not
contain device or user specific data.

666 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
34.6. ODK Aggregate

34.6 ODK Aggregate

34.6.1 Communications

When setting up your own web server to run ODK Aggregate, if you do not configure the
server and ODK Aggregate to use an SSL certificate, a determined observer can see all data
communicated to and from that server.
Encrypted Form Security can prevent a determined observer from viewing encrypted form
data being sent via insecure HTTP, but it cannot prevent the observer from silently removing
encryption from form definitions and capturing any unencrypted form data that is then
submitted.
Only transmissions over a secure HTTPS connection are obscured from observers and prevent
tampering in transmission.

34.6.2 Google App Engine and other Hosting Services

With all 3rd party hosting services, you should expect your data to be viewable by the
support staff of the hosting service. Different services go to differing lengths to restrict
access to, encrypt, and/or secure the data and communications within their data centers.
Encrypted Form Security can prevent hosting services from viewing encrypted form data
at rest, but cannot prevent the hosted service from silently removing encryption from form
definitions and viewing any unencrypted form data that is then submitted.
See Planning Your Aggregate Deployment for other considerations.

34.6.3 Username Authentication

When authenticating ODK Aggregate usernames and passwords, the ODK tools use Diges-
tAuth. This enables secure username/password authentication even while communicating
with servers over HTTP. When using DigestAuth, the password is not sent over the network.
An encoded form of the username’s password is stored on the server. If that encoded value
is stolen or revealed, it can allow others to log in and interact with the server as that user.

34.7 ODK Briefcase

We gather aggregate user behavior through Google Analytics and gather crash logs through
Sentry. We use secure HTTPS communication to transfer this data to ODK’s maintainers.
Users may disable analytics in the settings of the application. Crash logging cannot be
disabled.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 667
Chapter 34. Security and Privacy

34.8 ODK Build

We require secure HTTPS connections to ODK Build. We gather aggregate user behavior
through Google Analytics. We use secure HTTPS communication to transfer this data to
ODK’s maintainers.

34.9 ODK Collect

We gather aggregate user behavior through Google Analytics and gather crash logs through
Google Firebase Crashlytics. We use secure HTTPS communication to transfer this data to
ODK’s maintainers. Users may disable analytics in the settings of the application. Crash
logging cannot be disabled.

34.10 XLSForm Online

We require secure HTTPS connections to XLSForm Online. We gather aggregate user be-
havior through Google Analytics. We use secure HTTPS communication to transfer this
data to ODK’s maintainers.
XLSForm Online stores both your submitted XLS and the generated XML form for a period
of time on its disk drive before being deleted. This is necessary for the operation of the tool.
XLSForm Offline operates locally without any network communications and provides a secure
alternative to the convenience of XLSForm Online.

34.11 Cross-tool Concerns

34.11.1 Encrypted Form Security

The form definition and associated media files of an ODK encrypted form are stored on
the server in plaintext (unencrypted). The form definition and media files are transmitted
as plaintext (but perhaps through a secure HTTPS connection) to client devices (e.g., an
Android phone running ODK Collect) and stored in plaintext.
All form data (e.g., incomplete forms, saved forms) and media files are stored in plaintext
on the client device until they are finalized. It is only once the form data is finalized that
those files are encrypted.
At the time form data and media attachments are finalized, a random 256-bit encryp-
tion/decryption key is generated for that form data using the SecureRandom number gen-

668 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
34.11. Cross-tool Concerns

erator (found here). This ensures that every finalized form has its own unique 256-bit
encryption/decryption key.
The form data and media attachments are then encrypted with that key using 256-bit AES
Cipher Feedback (CFB) streaming-block encryption. Once encrypted, all plaintext form
data and attachments that were used in that process are deleted.
The random key is then padded and encrypted using the RSA public key declared in the form
definition (recommended to be 2048-bit) and the OAEPWithSHA256AndMGF1Padding al-
gorithm. The resulting encrypted key is transmitted to the server along with the encrypted
data and encrypted attachments. This submission includes a signature field that enables the
software to detect tampering to any of the encrypted attachments or to the encrypted form
data.
On the device, copies of the deleted plaintext form data and attachments may remain in the
free-list of the SD card until they are overwritten with new content.
On the server, if an observer were able to access your encrypted form data, since each form
submission uses a different key, each submission would need to be cracked separately.
The secret key required for decryption is never stored on the server, thereby preventing
anyone from seeing your form data and attachments unless they break the encryption.
Currently, cracking AES encryption is viewed as impossible for all but the most advanced
governmental agencies (for example, the NSA).

34.11.2 Identifying Information Transmission and Storage

During data submission, some identifying information is transmitted and stored on the server:
• ODK Collect passes the deviceID of the device to the server during the submission
process. The HEAD request that initiates the submission is a URL of the form: ...
/submission?deviceID=imei%3A9117DD011813771. The ODK Aggregate server does
not store this deviceID in any database tables, but it will generally be emitted into
the webserver access log. This deviceID uniquely identifies the device from which the
data is submitted. This can be useful when correlating events on the server with
interactions from specific devices. Because this is logged, it is likely that a submission
can be correlated with a device, and therefore a data collector.
• If ODK Aggregate is configured to require authentication for submission (that is, if the
Data Collector permission is NOT granted to the anonymousUser), then the username
that authenticated is written into the audit fields of the data tables storing the submis-
sion. If the anonymousUser is granted Data Collector privileges, no authentication is
performed, and anonymousUser is written into those fields. The content of these audit
fields is not exposed in exported CSV files, ODK Briefcase data pulls, or published to
downstream systems. However, because it is present in the database tables, you can
definitely correlate this authenticated username with the submitted data.

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 669
Chapter 34. Security and Privacy

While interacting with an ODK Aggregate website, any actions that require authentication
and that modify the server settings, set of form definitions, filters, exports, publishers, or
data tables, will cause the authenticated username to be written into the audit fields of the
database tables that are being updated. If these modifications result in delete actions being
performed against a database table, then this authenticated username will be identified in
the server log together with summary information on what was deleted.

See also:
Towards a Secure Framework for mHealth. A Case Study in Mobile Data Collection
Systems. Samson Hussien Gejibo. Ph.D. Dissertation at the University of Bergen,
2015.

670 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.
CHAPTER

THIRTYFIVE

GLOSSARY

Aggregate Part of ODK.


A server-side data storage and analysis tool.
Briefcase Part of ODK.
A tool for packaging and transferring forms and data between instances of Collect and
Aggregate.
Build Part of ODK.
An application that lets you design forms with a drag-and-drop form interface.
• Use ODK Build online.
• Download a desktop version of ODK Build.
Collect Part of ODK.
An Android mobile app that replaces paper-based forms.
CSV Comma Separated Values. A plain-text file format for tabular (spreadsheet-like) data.
enumerator A person who conducts a survey.
form A defined set of questions and answer choices displayed by an application that can
render forms written in the XForm standard.
hint Additional help text on a single question, displayed after the label.
instance The file representing a filled-in form.
JSON JavaScript Object Notation. A serialized key-value data format.
KML Keyhole Markup Language. A file format for geographic data.
ODK JavaRosa Part of ODK.
A Java library that renders ODK Compliant XForms.
ODK JavaRosa source on Github

Our documentation is updated frequently. Get the latest version at https://docs.getodk.org. 671
Chapter 35. Glossary

ODK XForm Part of ODK.


A specification defining valid XML-based forms for ODK. It is a subset of the W3C
XForms 1.0 specification
View ODK XForms Specification
participant A person being interviewed by a user of Collect. (Also sometimes called a
”subject”.)
question label
question text The main body of a form question or widget. In an XLSForm, the contents
of the label.
Validate Part of ODK.
A tool for validating forms against the ODK XForms specification.
widget A single question, answer set, and attendant GUI elements, as rendered in a XForm
compliant app such as Collect.
XLSForm Part of ODK.
A tool for building forms with Microsoft Excel.

672 Our documentation is updated frequently. Get the latest version at https://docs.getodk.org.

You might also like