A set of PHP / JS functions for helping jsPsych communicate with a MySQL database. These scripts allow you to:
- Check if a subject has already started the experiment in a previous session.
- Assign the subject to a condition in a (somewhat) balanced manner.
- Save data to a MySQL database.
There are three PHP scripts, one for each of the above tasks, plus a PHP config file.
The JS file is a client side library for communicating with the PHP.
-
Start by editing
php/database_config.php
. You will need to provide login information for an account withINSERT
,SELECT
, andSHOW
privileges for each of the three tables,$table_register
,$table_conditions
, and$table_data
. You can specify the names of these tables in the configuration file. -
Setup the MySQL tables. The PHP file expects three tables to be in the database.
$table_register
needs to have the columns row
, workerID
, and completionCode
.
row
should be an auto incrementing primary key.workerID
is the unique ID associated with your subject, e.g., a Mechanical Turk workerID.completionCode
is a randomly generated set of letters that you can use as a survey completion code that is unique to that subject, if desired.
$table_conditions
needs to have the columns row
, subjectID
, and assignedCondition
.
row
should be an auto incrementing primary key.subjectID
is an ID that you generate, e.g., usingjsPsych.randomization.randomID()
. You can use a Mechanical Turk workerID, but be aware that such IDs are not anonymous and that this could potentially create confidentiality problems.assignedCondition
will be an integer, generated by the server, indicating the condition assignment. If you have a design with multiple factors, then you need to convert this single integer to the appropriate level for each cell. For example, in a 2x2 design, assignedCondition could be 0, 1, 2, or 3. You should convert these 4 values to the 4 different cells in the 2x2.
$table_data
needs to have a column for each variable that you want to save from your jsPsych experiment. You can run the command jsPsych.data.get().uniqueNames()
after the experiment has completed to get a list of all the different variables that jsPsych is capturing in your experiment.
-
Upload the
js
andphp
files onto the server, in the same directory as your experiment files. -
Import the
serverComm.js
file into your jsPsych experiment.
<script src="js/serverComm.js" type="text/javascript"></script>
-
This library allows you to perform three different actions. You can register/exclude subjects, assign subjects to a condition, and save data. You can choose to use any of the features independently. My typical workflow is to register a subject and check if they have completed the experiment (excluding them if they have), then assign them to a condition, and finally save data at the end of the experiment.
-
To register/exclude subjects, use the function
serverComm.register_subject()
. This function takes a unique permanent identifier for the subject (e.g., a Mechanical Turk Worker ID), and checks to see if there is already a copy of that ID in the database. If there is, the functioncallback_exclude()
is executed. If there is not, then the WorkerID is added andcallback_success
is called. If there are any technical problems along the way (e.g., can't establish a database connection),callback_failure()
is executed. An example is shown below.
// this is an example of how you could extract the unique ID from the URL:
var id = jsPsych.data.getURLVariable('prolific_pid');
serverComm.register_subject(id,
function(){ // this is the success callback. the function executes if the subject has a unique id
continue_success();
},
function(){ // this is the excluded callback. show excluded message.
document.querySelector('body').innerHTML = '<p>Our records indicate that you have already started this experiment. Due to the nature of the experiment, restarting is not permitted.</p><p>If you believe this message is in error, you can contact the researchers at [email protected]. Our apologies for the trouble.</p>';
},
function(){ // this is the failure callback. show technical error message.
document.querySelector('body').innerHTML = '<p>Our apologies. There was a technical error on our end while loading the experiment.</p><p>You will not be able to complete the experiment. We are sorry for the trouble.</p>';
}
);
- To assign subjects to a condition, use the function
serverComm.assign_condition()
. This function takes a subject ID and the number of unique conditions in the experiment. I recommend not using the ID used for registering the subject because permanent IDs like Mechanical Turk worker IDs can lead to personally identifying information. Instead, I typically generate a random ID using the functionjsPsych.randomization.randomID()
. The function will execute thecallback_success(response)
function in the absence of technical failure, passing in the assigned condition asresponse.assignedCondition
. The script assigns conditions incrementally from 0 to n-1, where n is the number of unique conditions. If the previous subject had condition n-1, then the next subject will be assigned to condition 0. This sequential assignment of conditions is useful for experiments where an even distribution of subjects is desired and most subjects will complete the experiment in parallel, preventing the assignment of conditions based on the number of completed subjects in each condition. An example is shown below.
var subject_id = jsPsych.randomization.randomID(20);
var assigned_condition = null;
var n_conditions = 3;
serverComm.assign_condition(subject_id, n_conditions,
function(response){
assigned_condition = response.assignedCondition;
start_experiment();
},
function(){
document.querySelector('body').innerHTML = '<p>Our apologies. There was a technical error on our end while loading the experiment.</p><p>You will not be able to complete the experiment. We are sorry for the trouble.</p>';
}
);
- To save data, use the function
serverComm.save_data()
. This function takes an array of JavaScript objects to write to the database. jsPsych generates an array of objects where each object is a trial. An example is shown below using thecall-function
plugin to insert a trial that will save data. I prefer this pattern as opposed to using theon_finish
callback because it allows me to save the data before the final screen of the experiment, preventing accidental data loss when participants close the experiment at the final screen instead of finishing the experiment by clearing the final screen.
var save = {
type: 'call-function',
func: function(){
serverComm.save_data(jsPsych.data.get().values());
}
}
timeline.push(save);