The Barometer Survey Tool is a custom application developed to run the Global Data Barometer survey, but possible to adapt for other surveys. It provides for:
- User authentication - with surveys assigned to specific researchers and reviewers;
- In-line documentation, auto-saving responses, upload of supporting evidence;
- A survey workflow: including research, spot-check quality assurance, peer-review and updates to surveys;
- Custom question types, defined through a simple spreadsheet template;
- Notes feature to allow feedback on each individual survey element.
This application is an update of the Open Data Barometer survey tool to remove most of dependencies on Google infrastructure from the tool.
The survey tool implements a workflow with three main roles:
- Coordinator
- Primary researcher
- Reviewer
Each survey can be taken through a workflow covering:
- Initial research
- Spot check by coordinator
- Peer review - reviewers can comment but not update information
- Secondary research
- Spot check by coordinator
- Final validation
Surveys incorporates a range of question types, and conditional logic for the display of supporting questions.
The tool consists of a backend Django application that handles user authentication, and provides an API layer between the frontend app and Postgres database to: fetch survey definitions, save survey responses, and store and fetch supporting files.
The backend database makes extensive use of Postgres JSON fields to allow storage of flexible data structures. There is also a database log trigger set-up which will keep a full transaction history of database edits.
A frontend application written in Angular 1.3.20 uses survey definitions from the API to present a survey to authenticated users, who, depending on their role, may complete or comment on each question.
A control application is available written in Google Apps Script to create and manage surveys through a workflow of stages, and to send notification e-mails to users.
The frontend application allows users to create or log-in to an account on the system. Each account has a primary e-mail address attached to it which is used to identify surveys that the user has access to as a coordinator, researcher or reviewer.
The user can then access surveys with the following URL path: /{survey_id}/{question_data_name (optional)}
For example, if a user has been assigned survey 10 and question definitions exist for a default survey, for 'long_survey' and 'short_survey', they can access:
/10/long_survey/10/short_surveyand/10/
All will read the response data and notes stored for survey 10, but each will present a different set of questions. This can be used to provide respondents with slightly different surveys at different stages of a research if required.
Each question in the survey has an ID, Question and Type and a number of supporting fields used to affect the display of guidance, supporting questions, styling and other features (see question definition documentation below).
The files in /htdocs/tpl/ define how questions are displayed to the user, and allow for a flexible creation of new question types or changes to the way questions are laid out and structured.
Note: The current set of templates in this repository are configured specifically for the Global Data Barometer in the expectation that every question is structured as:
- A parent question of type 'Status' with
SubQuestionFirst= 'Yes' and withWantJustification,WantExamplesandHasPrivateNotesset at this level - One or more child questions without justification, examples or private notes
The Control Application is a Google Spreadsheet that will:
- Create new surveys and update their assignees and status
- Track completion of each survey
It is written in Google Apps Script. A template copy is available here (make a copy and use Tools -> Script Editor to see the scripts).
The control sheet needs two triggers configured to allow it to work. Triggers should be set up as a single user. This user will be the one whose account is used to send out notification mails etc.
- Go to Tools > Script Editor
- Choose Resources > Current Triggers
- Add two triggers - one for ‘onUpdate’ driven ‘From Spreadsheet’ by ‘On edit’ events, and the other for ‘periodicUpdate’ as a ‘Time-driven’ event on an hourly timer.
On updates, the control scripts check current survey completion, and put this into c_X columns, where X is the ID of a section in the survey.
As a control sheet may be used to assign various different surveys with different structures, an administrator should manually create columns left of the 'Completion Map' column to be poplated. These will contain the number of 'Status' questions with a status of 'Complete' or 'Reviewed'.
See .env.template for details of the different API keys and services needed to deploy a new copy of the appliation.
To create an admin user go to the console and run:
./manage.py createsuperuser
Tip: When deployed on Digital Ocean Apps, a web interface to the console is available from the Digital Ocean Cloud.
You can then log-in to the administration interface at tool-address.org/admin/
The build in Django Administration tool is mainly used to administer users. All other survey admin should take place using the API.
At /admin/auth/user/ you can see the user accounts created in the tool, and if required, update user passwords.
Once authenticated as a 'staff' user, you can access the full API at /api/
This uses the Django REST Framework to expose three endpoints:
/api/survey/- containing a record for each survey with control information (e.g. who is assigned to respond; survey status), question responses, review notes and associated files/supporting evidence./api/survey-data-types/- defines the templates used for recording control, responses, notes and file data. This is populated by fixtures, and would only need to change if there were modifications to the front-end application./api/question-data/- contains the survey definitions that determine the sections and questions contained for each survey. There is a default survey, and a collection of named surveys available at/api/question-data/list_names/
An authenticated user can GET, PUT or POST to most API endpoints in order to create or update surveys, or to define and update question data.
Note: the API was developed as a rapid drop-in replacement for deprecated Google APIs, and so has some quirks.
Question data consists of three parts:
- Config - providing general configuration variables for a set of questions. Exposed in
config.in angular. - Sections - setting up the sections used in the survey.
- Questions - setting up each individual question.
The easiest way to update question data is to create a Google Spreadsheet with tabs for 'Config', 'Sections' and 'Questions' following this template (see full documentation of fields below) and to set the spreadsheet to be accessible to anyone on the web. Then make a GET request with the spreadsheet key to:
/api/question-data/upload_spreadsheet/?name={SURVEY_NAME}&spreadsheet={SPREADSHEET_KEY}
The tool will then read and refresh the survey definitions from this file and save as {SURVEY_NAME}.
A survey is created by an authenticated user (HTTP Basic Auth) making a PUT request to /api/survey/ with the following JSON payload:
{
"control": {
"Coordinator Email": "coordinator@example.com",
"Coordinator Name": "Coordinator name",
"Country": "Survey title",
"Researcher": "lowercase MD5 hash of researcher e-mail address",
"Reviewer": "lowercase MD5 hash of reviewer e-mail address",
"Survey": "name of question_data to use",
"Status":" One of recruitment, assigned, spotcheck, clarification, review, validation or complete",
"Status Due":"DD-MM-YYYY"
}
}The API will return a survey control record with an assigned id.
To update the details of an existing survey, this can be PUT against /api/survey/{id}
Depending on the survey status, this will then let a user authenticated with the e-mail address hashed in 'researcher' or 'reviewer' to access the survey and provide responses or make review comments.
The data for each survey is available at /api/survey/{id}/data/. This can be used to fetch survey responses, although an alternative set of SQL queries for direct access to the database is also provided {TODO}.
The following section describes the format for a question data definition spreadsheet to use with the upload_spreadsheet feature. Column names are converted to lower-case, no space versions in the API.
All config values are passed to the the config. variable in Angular for use in front-end templating.
| Variable | Value | Notes |
|---|---|---|
| title | The survey title | |
| logo | URL to an image to use as survey icon/branding | |
| hide_question_id | FALSE | Should the ID of questions be displayed in the survey tool? |
| hide_notes | FALSE | Choose whether or not to enable to notes feature |
| justification_note | Justification and sources | What text should be displayed as a prompt for the justification and sources box? |
The spreadsheet template for config follows the table format above exactly.
The spreadsheet template for sections includes the columns listed below in classic table format.
| Column | How it is used |
|---|---|
| Section ID | A short alphanumeric identifier. Displayed in header bar |
| Section | An internal label for the section |
| Title | The title to display to users |
| Description | A section description displayed to users. Can contain Markdown |
| Column | How it is used |
|---|---|
| Section ID | Matches the ID of the section this question is included in |
| Question ID | A unique identifier for the question |
| Question Type | Matching a type for which a template exists in tpl/question.html - currently Note, Option, Description, Scale, Status, Sum, ElementGroup, Element and Radio |
| Parent ID | If provided, this question is grouped under the parent ID. Tree structures can be created this way |
| SubQuestionsFirst | Should child questions be displayed before the substantive part of this question (and before justification/sources for this question) |
| CSSClass | An optional custom CSS class to attach to the question container |
| Guidance10 | Scale questions ask for a response in the range 0 - 10, and can provide guidance for steps of the scale. If using a scale question this will provide guidance on what should count as 10 out of 10 |
| Guidance5 | ditto for 5 out of 10 |
| Guidance0 | ditto for 0 out of 10 |
| WantConfidence | Answer 'Yes' if the user should provide a rating of how confident they are in their reply |
| WantJustification | Answer 'Yes' if the user should provide a free text justification for their response |
| JustificationNote | An optional prompt text to overwrite the default prompt for justification and sources |
| HasPrivateNotes | Answer 'Yes' if the user should provide private notes for the reviewer / coordinator |
| WantExamples | Answer 'Yes' if the user should be able to attach URLs or Files to this question |
| Multiplier | A value between 0 and n to multiply the option response by when using this question as the child of a 'Sum' question. For example, if Multiplier = 0.5, then answering Option 3 adds 1.5 to the parent Sum value |
| OptionGuidance | An optional free text string to display in-line guidance on options presented to the user |
| Option{0-9} | Options presented to the user in Scale, Option, Radio and Element questions |
| Supporting{0-5} | Freetext supporting questions to display. Responses are collected as unvalidated free text. Questions can be made conditional on option responses by prefixing with "{OptionN},{OptionN};Supporting question text". For example, to only display a question if the user responds with Option2 or Option3, Supporting0 would be "2,3;If option 2 or 3, then explain why?" |
| HelpLink | The URL of further question guidance, to be openned in-line |
Original concept and prototype developed in 2013 by Tim Davies for the World Wide Web Foundation. Front-end application developed by Oomph Inc in 2014 with some of the funding for this work originating in the open data common assessmnet methods component of IDRC grant 107075. Subsequent developed undertaken by Carlos Iglesias of the World Wide Web Foundation. Updates to front-end by Ali Blackwell. Re-write of backend system by David Raznick of Open Data Services Co-operative. Further updates and Documentation by Tim Davies.