A lead researcher explaining the benefits of Cognition.run

Behavioral Experiments in the Digital Age: The Cognition and jsPsych Advantage

What a behavioral experiment is

A behavioral experiment manipulates something and measures what a person does in response. The thing you manipulate is the independent variable: the color of a word, the delay before a reward, whether a face is familiar. The thing you measure is the dependent variable: how fast the participant responds, whether the response is correct, which option they choose, or how they rate something on a scale. Everything else is held constant or randomized so that differences in the dependent variable can be attributed to the manipulation.

The three most common dependent measures in cognitive and behavioral work are:

  • Reaction time (RT), in milliseconds from stimulus onset to response. Typically analyzed after removing errors and extreme values.
  • Accuracy, the proportion of correct responses, or signal-detection measures derived from hits and false alarms.
  • Choice, which of several options was selected, as in economic games or preference tasks.

Designs are either within-subject (each participant sees every condition, and you compare conditions within a person) or between-subject (each participant is assigned to one condition). Within-subject designs are more powerful and are the default for most reaction-time paradigms; between-subject designs are needed when exposure to one condition would contaminate another.

Anatomy of a jsPsych experiment

jsPsych structures an experiment as a timeline: an ordered array of trials. Each trial is a plain JavaScript object whose type is a plugin (a component that knows how to display one kind of stimulus and collect one kind of response). Plugins exist for keyboard and button responses, images, audio, video, sliders, Likert scales, free text, instructions and more.

Instead of writing one trial object per stimulus, you write a template trial once and feed it a list of timeline variables. jsPsych then loops over the list, optionally in random order and with repetitions. Every trial produces a row of data, and you can attach your own properties (condition labels, the correct answer) so the exported file is ready for analysis.

Here is a complete simple reaction-time task with two conditions, written for jsPsych 8:

const jsPsych = initJsPsych();

const stimuli = [
  { stimulus: "<p style="font-size:48px">&#9679;</p>", condition: "dot" },
  { stimulus: "<p style="font-size:48px">&#9632;</p>", condition: "square" }
];

const fixation = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: "<p style="font-size:48px">+</p>",
  choices: "NO_KEYS",
  trial_duration: () => jsPsych.randomization.sampleWithoutReplacement([400, 600, 800], 1)[0]
};

const target = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: jsPsych.timelineVariable("stimulus"),
  choices: [" "],
  trial_duration: 1500,
  data: { task: "srt", condition: jsPsych.timelineVariable("condition") },
  on_finish: (data) => {
    data.responded = data.response !== null;
  }
};

const timeline = [
  {
    type: jsPsychInstructions,
    pages: ["<p>Press the space bar as soon as a shape appears.</p>"],
    show_clickable_nav: true
  },
  {
    timeline: [fixation, target],
    timeline_variables: stimuli,
    randomize_order: true,
    repetitions: 20
  }
];

jsPsych.run(timeline);

This produces 40 target trials (two shapes, twenty repetitions each) in random order, each preceded by a jittered fixation cross. The data for each target trial includes rt, response, and the condition label you attached, so comparing mean RT for dots versus squares is a one-line operation in R or Python. Note that data.rt and data.response are null on trials where the participant did not respond within 1500 ms.

A choice reaction-time task (press F for one shape, J for the other) needs only two changes: choices: ["f", "j"] and a correct_response timeline variable compared in on_finish with jsPsych.pluginAPI.compareKeys(data.response, data.correct_response). For a worked example, see the Stroop tutorial.

What Cognition adds

jsPsych gives you the experiment; it does not give you a server, data storage, consent forms or participant management. Cognition handles that layer, and it does so in ways that matter for the validity of a behavioral experiment:

  • Hosting with a live editor. Paste the code above into the editor, see a live preview with an error console, upload images or audio, and get a https://<token>.cognition.run link over HTTPS. jsPsych 6.0.5 through 8.2.3 are supported.
  • Real-time data capture. Each trial is sent to the server as it finishes. If the participant's connection drops, a service worker stores trials locally and resends them when it returns. When the experiment ends, everything is confirmed uploaded before your own on_finish runs, so redirects to Prolific never lose data.
  • Balanced between-subject conditions. Set the number of conditions and Cognition assigns participants on the server so groups stay balanced. The assignment is available in your code as window.CONDITION (1 to N).
  • Informed consent. Write the consent text in markdown; participants who decline are sent to a URL you choose and never reach the experiment.
  • Single-use links. Generate up to 500 per batch so each participant can run the task only once, and stop recruitment now, on a date, or after a set number of participants.
  • Export and analysis. Download CSV or JSON (one file or a ZIP per participant); URL parameters such as PROLIFIC_PID appear as columns on every trial. A built-in analyzer covers t-tests, ANOVA and plots for a first look at the data.

See it running

The best way to understand the combination is to run a task as a participant. These demos are hosted on Cognition and their source is available:

When you are ready to host your own, create a free account. The free plan includes four tasks with up to sixty participants each, enough for piloting and for most classroom projects. The documentation covers the details of data format, conditions and integrations.