schema

March 8, 2022 ยท View on GitHub

schema

schema

GooglePlay AppStore

schema is a cross-platform mobile application for deploying mHealth monitoring and intervention studies.

It supports:

  • A diverse range of elements, including slider, text input, date/time, audio, video, image, and more, with support for branching logic.
  • Flexible module scheduling, to deliver surveys and/or interventions to participants at random or fixed intervals.
  • Participant randomisation into distinct conditions with different modules and scheduling.
  • Study registration via scanning a QR code or directly entering protocol URL.
  • Dynamic feedback charts to track participant progress on specific variables.
  • Distributed architecture, such that study protocols and data can be stored on your own server.

Citation

If you use schema in your own research, please cite the following:

Shatte, A. B. R., & Teague, S. J. (2020). schema: An open-source, distributed mobile platform for deploying mHealth research tools and interventions. BMC Medical Research Methodology, 20(1), 1-12. Retrieved from https://bmcmedresmethodol.biomedcentral.com/articles/10.1186/s12874-020-00973-5

Shatte, A. B. R., & Teague, S. J. (2019, June 12). schema (Version 1.0). Zenodo. http://doi.org/10.5281/zenodo.3243918

DOI

Usage

Dependencies

schema depends on the following frameworks:

  • Ionic - Cross-platform mobile app development
  • node.js - Cross-platform JavaScript run-time environment
  • Chart.js - Open source HTML5 charts

Plugins

schema uses the following Ionic Native plugins to achieve native functionality:

PluginDocumentation
Barcode Scannerhttps://ionicframework.com/docs/native/barcode-scanner
LocalNotificationshttps://ionicframework.com/docs/native/local-notifications
SQLitehttps://ionicframework.com/docs/native/sqlite
FileTransferhttps://ionicframework.com/docs/native/file-transfer
Filehttps://ionicframework.com/docs/native/file

Installation

Install the dependencies and platforms

$ cd schema
$ ionic cordova prepare

The Ionic Docs contain detailed instructions on the next steps.

Localisation

schema uses the ngx-translate library for translation. If you wish to contribute a localised version of the app's strings in another language, the file src/assets/i18n/en.json should be used as a template.

Deploying a study

To host your own study on the schema platform, the following steps are required:

  • Create a study protocol and upload it to a web server (follow the instructions below)
  • Create a page on a server to receive post requests and save data

Study protocol

A study protocol is defined in a JSON file. At the highest level, this file contains two attributes: the properties object which stores the metadata about the study; and the modules array which stores the individual survey/intervention tasks that will be delivered to the participants.

{
  "properties": {
    /* property attributes */
  },
  "modules": [
    /* module objects */
  ]
}

We recommend using a GUI service like JSON Editor Online to build your study protocol.

Properties

The properties object must define the following attributes:

PropertyTypeDescriptionExample
study_idStringAn identifier for the study which is sent to the server with response data."study_id":"ABC123"
study_nameStringThe name of the current study."study_name": "Sleep Study"
instructionsStringBrief description/instructions for the study that is displayed in the app. Basic HTML supported."instructions": "This study will track your sleep."
banner_urlStringThe URL to an image that will be displayed on the home page of your study. It will be displayed at 100% width and maintain the aspect ratio of the original image."banner_url": "https://getschema.app/banner.png"
support_emailStringAn email address that participants can contact for support with the study."support_email": "support@getschema.app"
support_urlStringA web link to the study's homepage or support information that is linked to in the app."support_url": "https://getschema.app/"
ethicsStringAn ethics statement for the study."ethics": "This study was approved by ethics committee with approval number 0093423"
plsStringA web URL to a PDF file containing the study's Plain Language Statement."pls": "https://getschema.app/pls.pdf"
empty_msgStringA message displayed to the user when there are no tasks currently available to complete."empty_msg": "Relax, you're all up to date."
post_urlStringAn endpoint to receive participant responses (POST data) from the app."post_url": "https://getschema.app/post.php"
conditionsArrayA list of conditions that participants can be randomised into."conditions": [ "Control", "Intervention" ]
cacheBooleanIndicates whether media elements will be cached for offline mode during study enrollment. Note: media should be optimised to reduce download times."cache": true

Modules

The modules array contains one or many module objects, which encapsulate the surveys and/or interventions that will be delivered to the participants of your study. A module object has this high-level structure:

{
  "type": "...",
  "name": "...",
  "submit_txt": "...",
  "condition": "...",
  "alerts": {
      /* alert properties */
  },
  "graph": {
      /* graph properties */
  }, 
  "sections": [
      /* section objects with questions */
  ]
 }

The properties of a module object are defined as follows:

PropertyTypeDescriptionExample
typeStringThe type of the module. Accepted values are survey, info, video, and audio."type": "survey"
nameStringThe name of the module. Basic HTML supported."name": "Daily Checklist"
submit_txtStringThe label of the submit button for this module. Note: this value appears only on the final section of a module."submit_txt": "Finish"
conditionStringThe condition that this module belongs to. It must match one of the values from the conditions array from the study properties, or have the value * to be scheduled for all participants."condition":"Control"
alertsObjectContains information about the scheduling of this module. Used to control access to the task and set notifications.See alerts.
graphObjectContains information about the graph relating to this module (if any). Used to render the graph in the Feedback tab.See graph.
sectionsArrayAn array of section objects that contain the questions/elements for this module.See sections.
uuidStringA unique identifier for this module."uuid": "5f8c6ec7-463d-4e51-9ea3-480115bd9f53"
unlock_afterArrayA list of UUIDs of modules that must be completed before this module will appear on the task list."unlock_after": [ "b79bc562-1dd2-4c3f-a1ed-6bb359cbfaaa" ]
shuffleBooleanUsed for counterbalancing. If true, the order of the sections will be randomised every time the module is accessed."shuffle": true
Alerts

The alerts object must define the following attributes:

PropertyTypeDescriptionExample
titleStringThe title that is displayed in the notification (main text)."title": "Time to check in!
messageStringThe message that is displayed in the notification (secondary text)."message": "Tap here to open the app."
start_offsetIntegerIndicates when the module should first be displayed to the user, where zero is the day that the participant enrolled."start_offset": 1
durationIntegerIndicates the number of consecutive days that the module should be scheduled to display."duration": 3
timesArrayThe times that this module should be scheduled for each day. hours indicates the hours (24-hour time) and minutes indicates the minutes (so should be between 0 and 59)."times": [ { "hours": 8, "minutes": 30 } ]
randomBooleanIndicates whether the alert times should be randomised. If true, each value from times will be set using the value of random_interval."random": true
random_intervalIntegerThe number of minutes before and after that an alert time should be randomised. For example, if the alert is scheduled for 8.30am and the random_interval is 30, the alert will be scheduled randomly between 8 and 9am."random_interval": 30
stickybooleanIndicates whether the module should remain available in the Tasks list upon response, allowing the user to access this module repeatedly."sticky": true
sticky_labelStringA title that appears above a sticky module on the home screen. Multiple sticky modules that are set to appear in succession will be grouped under this title."sticky_label": "Warm up videos"
timeoutBooleanIf timeout is true, the task will disappear from the list after the number of milliseconds specified in timeout_after have elapsed (if the module is not completed before this time)."timeout": true
timeout_afterIntegerThe number of milliseconds after a task is displayed that it will disappear from the list. timeout must be true for this to have any effect."timeout_after": 300000
Graph

The graphs object must define the following attributes:

PropertyTypeDescriptionExample
displayBooleanIndicates whether this module displays a feedback graph in the Feedback tab. If the value is false, the remaining variables are ignored."display": true
variableStringThe id of a question object to graph. It must match one of the module's question ids."variable": "q4"
titleStringThe title of the graph to be displayed in the Feedback tab."title": "Daily sleep"
blurbStringA brief description of the graph to be displayed below it in the feedback tab. Basic HTML supported."blurb": "Your daily sleep in hours"
typeStringThe type of graph. Currently bar and line are supported."type": "line"
max_pointsIntegerThe maximum number of data points to display in the graph, e.g. 10 will only show the ten most recent responses."max_points": 10
Sections

The sections array contains one or many section objects, which have this high level structure:

{
    "name": "Demographics",
    "questions": [
        /* question objects */
    ]
}

The properties are defined as follows:

PropertyTypeDescriptionExample
nameStringThe title of this section, which is displayed at the top of the screen."name": "Demographics"
questionsArrayAn array containing all of the questions for this section of the module.See questions.
shuffleBooleanUsed for counterbalancing. If true, the order of the questions in this section will be randomised."shuffle": true

Questions

There are several types of question object that can be added to a section, including:

  • Instruction
  • Text Input
  • Date/Time
  • Yes/No (boolean)
  • Slider
  • Multiple Choice
  • Media

All question objects must include the following properties:

PropertyTypeDescriptionExample
idStringA unique id to identify this question. This id is sent to the server along with any response value. Note: Every element in the entire study protocol must have a unique id for some features to function correctly."id": "q1"
typeStringThe primary type of this question. Accepted values are instruction, datetime, multi, text, slider, video, audio, and yesno."type": "slider"
textStringThe label displayed alongside the question. Basic HTML supported."text": "How do you feel?"
requiredBooleanDenotes whether this question is required to be answered. The app will force the participant to answer all required questions that are not hidden by branching."required": true

Many question types have additional properties that they must include, which are outlined in the following sections.

Text Input

Text Input questions must have the following additional property:

PropertyTypeDescriptionExample
subtypeStringThe specific type of text input for this field. Accepted values are short, long, and numeric."subtype": "long"
Date/Time

Date/Time questions must have the following additional property:

PropertyTypeDescriptionExample
subtypeStringThe specific type of date/time input for this field. Accepted values are date (datepicker only), time (timepicker only), and datetime (both)."subtype": "time"
Yes/No

Yes/No questions must have the following additional properties:

PropertyTypeDescriptionExample
yes_textStringThe label for a true/yes response."yes_text": "Agree"
no_textStringThe label for a false/no response."no_text": "Disagree"
Slider

Slider questions must have the following additional properties:

PropertyTypeDescriptionExample
minIntegerThe minimum value for the slider range."min": 0
maxIntegerThe maximum value for the slider range."max": 100
hint_leftStringA label displayed to the left of the slider."hint_left": "less"
hint_rightStringA label displayed to the right of the slider."hint_right": "more"
Multiple Choice

Multiple choice questions must have the following additional properties:

PropertyTypeDescriptionExample
radioBooleanDenotes whether the multiple choice should be radio buttons (one selection only) or checkboxes (multiple selections allowed)."radio": true
modalBooleanDenotes whether the selections should appear in a modal popup (good for longer lists)"modal": false
optionsArrayThe list of choices to display."options": [ "Dog", "Cat", "Fish" ]
shuffleBooleanIf true, the order of the choices will be randomly shuffled."shuffle": true
Media

Media questions must have the following additional properties:

PropertyTypeDescriptionExample
subtypeStringThe type of media. Accepted values are video, audio, and image."subtype": "video"
srcStringA direct URL to the media source."src": "https://getschema.app/video.mp4"
thumbStringRequired for video elements. A direct URL to the placeholder image that is displayed in the video player while loading."thumb": "https://getschema.app/thumbnail.png"

Branching

To use branching, you need to add two additional properties to the question object that is to be dynamically shown/hidden.

PropertyTypeDescriptionExample
hide_idStringThe id of the question that will trigger this question to dynamically show/hide."hide_id": "q5"
hide_valueString/BooleanThe value that needs to be selected in the question denoted by hide_id which will make this question appear. When using sliders, the value should be prefixed with a direction and is inclusive, e.g. >50 or <50."hide_value": "10"
hide_ifBooleanIndicates the branching behaviour. If true, the element will disappear if the value of the question equals hide_value. If false, the element will appear appear instead."hide_if": false

Currently, branching is supported by the multi, yesno, and slider question types.

Randomisation of elements

Elements can also be grouped for randomisation, such that every time a module is accessed only one of the random elements will be displayed. An example use case would be to display a random image from a set of images. To achieve this, add the following property to each group of elements:

PropertyTypeDescriptionExample
rand_groupStringAn identifier that groups a set of elements together so that only one will randomly appear every time a module is accessed. Note: To identify which element was visible, it will be given a response value of 1. If the element can record a response this value will be replaced with that response. All hidden elements will record no response."rand_group": "sad_images"

Collecting data

The post_url defined in the study protocol's properties object should point to an endpoint that can receive POST requests. The endpoint should return the boolean value true if data has been successfully saved - schema will continue submitting each data point to the server until it receives this acknowledgement.

schema posts the following variables to the server whenever a task is completed:

POST idTypeDescription
data_typeStringDescribes whether log or survey_response data is being submitted.
study_idStringThe identifier of the study taken from the study_id property of the study protocol.
user_idStringThe unique id of the user.
module_indexIntegerThe index of the module in the modules array (zero-based).
platformStringThe platform the user responded on. Value will be iphone, ipad or android.

For survey_response data, these additional variables are included:

POST idTypeDescription
module_nameStringThe name of the module.
responsesStringThe questions responses for this task, provided as a stringified JSON object. The key is the id of the question, for example { "q1": 56 , "q2": "No", "q3": "" }.
response_timeTimestampThe timestamp when the module was completed, in the user's local time, e.g. 2019-05-08T23:16:21+10:00.
alert_timeTimestampThe timestamp when the module was first scheduled to appear, e.g. 2019-05-08T23:00:21+10:00.

For log data, these additional variables are included:

POST idTypeDescription
pageStringThe page the user visited in the app. Value can be home, my-progress, settings, or survey. If survey, the module_index variable will differentiate which module was accessed.
timestampTimestampThe timestamp when the user visited the page, e.g. 2019-10-29T16:08:58+11:00.

Distribution

Participants can sign up to your study by scanning a QR code or entering a URL. Upload your JSON study protocol to a web server and distribute the link. We recommend using a service like QRCode Monkey to generate a QR code that points to your study protocol link. The URL can be shortened for distribution using Bitly.

Testing your program

The variability in devices that support mHealth apps and the diversity of possible research designs within schema may result in unintended bugs. Therefore it is important that you conduct thorough testing of any program you deploy to schema before sharing it with participants.

Feedback

Please post any bugs, issues or suggested features in the Issues tab.

Localisation

schema uses the ngx-translate library for translation. If you wish to contribute a localised version of the app's strings in another language, the file src/assets/i18n/en.json should be used as a template. Follow the documentation from ngx-translate to determine the correct name for your language file.

License

License: MIT