In all the experiments we’ve built so far, it has been assumed that a “trial” consists of a single stimulus to which a participant must give a response. By varying the stimulus type and the response type this produces a family of R functions that map onto different jsPsych plugins. In my experience these are the most common kinds of trials that one wishes to use, but there are also a variety of more specialised situations for which jsPsych supplies dedicated plugins. We’ve seen one example of this already, namely the trial_instructions() function. There’s nothing stopping you from presenting instructions as a series of trial_html_button_response() trials, but it’s tedious to build and it is hard (not impossible) to allow participants to browse the instruction set using forward and back buttons. So this is a situation where the specialised plugin is handy.

Another very common scenario where a specialised plugin is handy is if you want to include an entire page of survey questions. It would of course be quite easy to create a single survey question using trial_html_button_response(), and create a complete survey by using many such questions, but it is sometimes inconvenient. To make surveys a little simpler, jsPsych has plugins for five different kinds of survey page, four of which are currently supported in jaysire. The four supported types are:

  • Pages where every survey question is a multiple choice question (i.e., choose exactly one option) can be created using the trial_survey_multi_choice() function
  • Pages where every survey question is a multiple selection question (i.e., select as many options as are applicalbe) can be created using the trial_survey_multi_select() function
  • Pages where every survey question is a Likert scale item can be created with trial_survey_likert()
  • Pages where every survey question asks for a free text response can be created with trial_survey_text()

The jsPsych library does not have specialised plugins for the case where a survey page can contain questions of different types, and as a consequence neither does jaysire.


Creating a question

Because a survey page can include more than one question, the jaysire package provides convenience functions that allow you to build questions. For instance, if you want a likert scale question you could do something like this:

which defines a 5 point Likert scale item, and marks it as a required question. If you want to create a multiple choice or multiple selection question, then you can use question_multi(), which (following the convention in jsPsych) refers to response options for multiple choice trials, in contrast to the scale labels used by question_likert(). Here is an example:

  prompt = "Choose your awesomeness",
  options = c("Kittens", "Puppies", "Otters", "Ducks", "Axolotls")

Note that you don’t need to specify whether this is a multiple choice question or a multiple selection question: if you embed it in a trial_survey_multi_choice() page it will be presented as a multiple choice question, but if you embed it in trial_survey_multi_select() it will appear in a “choose as many as apply” format.

Finally, you can define a free response question using question_text() like so:

When embedded on a trial_survey_text() this question will appear with a text response box underneat that spans 10 rows and 60 columns. The placeholder text will be shown greyed out within the box.

Composing a page of questions

At this point, our next task in writing a survey is to put together a list of questions that can be passed to one of the survey items. For example, suppose we wanted a page that asks for some basic demographic information. This page would contain a short preamble that would be displayed at the top of the page, and then show a list of multiple choice questions underneath. Once all of the required questions are answered, a button can be pressed to continue to the next page. Here is how we could do that:

Notice that the questions argument is a list of questions. When you have two or more questions to include, this is mandatory, but if there is only one question jaysire will allow you to pass the question directly like so:

When creating Likert pages, it is very common to reuse the same labels for every question, so it can be convenient to create a page of Likert items like this:

Example experiment


page1 <- trial_survey_multi_choice(
  preamble = "Welcome! We'd like to ask some demographic questions",
  questions = list(
      prompt = "Please select the option that best matches your gender",
      options = c("Male", "Female", "Nonbinary", "Other", "Prefer not to say"),
      name = "gender"
      prompt = "Do you consider yourself to be LGBTIQ+?",
      options = c("Yes", "No", "Unsure", "Prefer not to say")

page2 <- trial_survey_multi_select(
  questions = question_multi(
    prompt = "Which of the following R packages to you use?",
    options = c(
      "ggplot2", "dplyr", "purrr", "janitor", "data.table", "testthat",
      "usethis", "tibble", "magrittr", "rlang", "babynames", "janeaustenr"

confidence_scale <- c(
  "Very unconfident", 
  "Somewhat unconfident", 
  "Somewhat confident", 
  "Very confident"

page3 <- trial_survey_likert(
  preamble = "How confident in you R skills?",
  questions = list(
    question_likert("Data wrangling?", confidence_scale),
    question_likert("Data visualisation?", confidence_scale),
    question_likert("Statistical modelling?", confidence_scale),
    question_likert("Designing experiments?", confidence_scale),
    question_likert("R markdown documents?", confidence_scale)

page4 <- trial_survey_text(
  questions = question_text(
    prompt = "Anything else you would like to mention?",
    placeholder = "Type your answer here",
    rows = 8,
    columns = 60

  timeline = build_timeline(page1, page2, page3, page4),
  path = temporary_folder(), 
  on_finish = save_locally()
#> Warning in dir.create(path): '/tmp/RtmpRsDJCg/jaysire_j5lxa' already exists

You can check out a working version of the experiment here.