Introduction

PsychLab.IO Documentation

PsychLab.IO is a browser-based platform for building, running, and collecting data from psychology experiments with no programming required. Drag nodes onto a canvas, configure their properties, and share a link. Responses are saved to your account automatically.

Quick start

Your first experiment

  1. 1

    Create an experiment

    Go to Dashboard → Experiments → New experiment. Choose a template or start from scratch.

  2. 2

    Build your timeline

    Drag nodes from the left palette onto the canvas. Arrange them into a sequence: instructions, fixation, stimulus, feedback, and so on.

  3. 3

    Configure properties

    Click any node to open its properties in the right panel. Changes save automatically.

  4. 4

    Test it

    Open the experiment page from the dashboard and click Run. Draft experiments do not record data.

  5. 5

    Activate to collect data

    Set the status to Active. Share the participant link. Responses flow in automatically.

The builder

Builder overview

Node palette

Left panel. Lists all available node types. Drag any node onto the canvas to add it.

Canvas

Center panel. Your experiment timeline as a tree. Drag nodes to reorder them.

Properties panel

Right panel. Configuration for the selected node. Changes save automatically; the header shows "Saved", "Saving…", or "Unsaved".

Timeline strip

The strip at the bottom shows a proportional view of experiment timing. Branching conditions appear on parallel lanes. Click a segment to select that node.

Resizing panels

Drag the dividers between panels to resize them.

Node reference

All nodes

Every experiment is built from nodes in one of four categories: structure, flow, display, and data.

Structure

Sequence

container

Runs its children one after another in order. No configurable properties.

Repeat

container

Two modes. Fixed count: runs children a set number of times. Trial list: iterates over conditions, exposing the current condition as _trial.

PropertyDescription
repeatCountNumber of repetitions, fixed count mode (default 2)
trialSourcebalanced_shuffle or manual; enables trial list mode
conditionsCondition labels to shuffle across (balanced_shuffle mode)
trialCountTotal number of trials to run (balanced_shuffle mode)
trialsExprAny iterable TypeScript expression (manual mode)

Flow

If

container

Runs the "then" branch when the condition is true, the "else" branch otherwise. Supports else-if chains.

PropertyDescription
conditionTypecorrect, incorrect, no_response, key_is, trial_is, group_is, or custom
conditionKeyKey code to match (key_is)
conditionValueValue to match (trial_is / group_is)
predicateCustom TypeScript expression (custom)
hasElseWhether to include an else branch

Loop

container

Repeats its children as long as the condition remains true. Useful for re-showing a stimulus until the participant responds correctly.

PropertyDescription
conditionTypeSame options as If node
conditionKey / conditionValue / predicateSame as If node
loopMaxIterSafety cap; max iterations before the loop exits (default 50)

Counterbalance

Assigns each participant to a named group at the start of the experiment. The group is stored in _group for the rest of the session. Use If → group is… to branch per group.

PropertyDescription
cbModerandom: random assignment; sequential: fills the least-populated group; url_param: reads from a URL query parameter
cbGroupsList of group names (e.g. control, treatment)
cbParamURL parameter name for url_param mode (default group)

Sequential mode uses a server-side atomic counter so group sizes stay balanced under concurrent participants.

Display

Instructions

Shows a text screen and waits for Space.

PropertyDescription
textInstruction text. Newlines are preserved.
sizeFont size in px (optional)
colorText colour (default white)
alignleft, center, or right (default center)

Fixation

Displays a fixation cross for a set duration. Enable random range to jitter duration between min and max each trial.

PropertyDescription
durationFixed display time in ms (default 500)
durationMin / durationMaxRange for random-range mode
fixSizeCross arm length in px (optional)
thicknessCross stroke width in px (optional)
colorCross colour (default white)

Stimulus

Displays a stimulus and waits for a key response. Three types: text, image, and rectangle. Records reaction time and response accuracy.

PropertyDescription
stim.typetext, image, or rect
stim.contentStatic text. Toggle {} for a TypeScript expression.
stim.fontSizeFont size in px (default 48, text type)
stim.colorText colour. Toggle {} for a dynamic expression.
stim.pathPath or URL to image file (image type)
keysAccepted key codes, e.g. KeyF, KeyJ
correctKeyKey that counts as correct. Toggle {} for a dynamic expression.
timeoutMax wait time in ms before moving on (default 1500)

Blank

A silent screen for inter-stimulus or inter-trial intervals.

PropertyDescription
durationPause duration in ms (default 800)
colorBackground colour (default black)

Feedback

Displays text feedback after a response. Three modes: Correct / Incorrect, With timeout (adds a third branch for no response), and Always show (fixed message).

PropertyDescription
feedbackTypecorrect_incorrect, with_timeout, or always
correctText / incorrectText / timeoutTextText per outcome
correctColor / incorrectColor / timeoutColorColour per outcome
durationDisplay time in ms (default 600)

End Screen

A final thank-you or debrief screen. Automatically advances after the set duration, or waits for Space if no duration is set.

PropertyDescription
textMessage to display. Newlines are preserved.
durationHow long to show the screen in ms. Leave blank to wait for Space.

Data

Record

Appends a row to the in-memory trial log. Add fields by name and give each a TypeScript expression. Data is sent to the server when the experiment ends.

PropertyDescription
fieldsArray of { name, expr } pairs evaluated at runtime

Expressions

Dynamic values

Toggle the ƒ button next to a field to switch it to expression mode. Expressions are plain JavaScript evaluated at runtime.

VariableTypeDescription
_trialstringCurrent condition label from a Repeat node in trial-list mode
_lastRespstring | nullKey code of the most recent response (e.g. "KeyF"), or null on timeout
_lastCorrectbooleanWhether the last response was correct
_lastRtnumber | nullReaction time of the last response in ms, or null on timeout
_groupstringGroup assigned by a Counterbalance node

Examples

Show the current condition as the stimulus text

_trial

Set the correct key based on the trial condition

_trial === 'left' ? 'KeyF' : 'KeyJ'

Loop while the participant keeps responding incorrectly

!_lastCorrect

Record reaction time in a Record node field

_lastRt

Running experiments

Running & data collection

Consent

If you add consent text to an experiment, participants will see a consent screen before the experiment starts. They can agree to proceed or decline. If they decline, no data is recorded and the session ends immediately.

Participant ID

Each participant is automatically assigned a UUID on their first visit, stored in localStorage per experiment. This ID is attached to all data saved by that session. If a participant clears their browser storage and revisits the link, they will receive a new ID.

Data flow

The experiment runs entirely in the browser. When it ends, all recorded rows are sent to /api/results as a JSON payload with a header object (experiment name and participant ID) and a trials array.

Statuses

StatusMeaning
draftIn development. You can run it to test, but responses are not recorded.
activeOpen for participants. Share the experiment link to collect data.
closedNo longer accepting responses. Existing data is preserved.

Plans & limits

Free vs Pro

Free

  • - Up to 3 experiments
  • - 60 responses per month
  • - All node types & templates

Pro

$5 / month
  • Unlimited experiments
  • Unlimited responses
  • Everything in Free

Monthly response counts reset at the start of each calendar month. If a free account reaches 60 responses mid-month, subsequent saves will return a monthly_limit_reached error and no further data will be recorded until the next month.