Collecting Data with Flash in Qualtrics, via Javascript

For online, reaction-time based experiments I use Adobe Flash programs to collect data (ala Simcox & Fiez, 2013). So far, this has meant hosting the Flash program on a private server, exporting the data as an XML object to a PHP script that then converts it into a CSV file for download. My PHP scripts are an ActionScript 3 (AS3) version of the (very helpful) AS2 code developed by Jeff Galak for his “Flash for Behavioral Researchers” workshops.

However, as I also use Qualtrics to host and distribute surveys, I worked out how to collect data from an embedded Flash program using JavaScript, instead of PHP. I have not tested it, but this method might also be adaptable for Flash programs on Amazon Mechanical Turk.

I’ve explained the method in detail for anyone who wants to get started. Nota bene: Follow my advice at your own risk, and make sure to do your own homework.

[This post has been updated as of 9/13/2014, after several implementations of this method in actual studies.]

Overview of How it Works

This method makes use of the External Interface object in ActionScript 3 and the setEmbeddedData() function from the Qualtrics JavaScript API.

ExternalInterface is an AS3 Flash object that allows us to pass information between an embedded SWF file and JavaScript functions on the same HTML page. Qualtrics.SurveyEngine.setEmbeddedData() is the JavaScript function provided by Qualtrics that can modify the values of Embedded Data objects in the Survey Flow.

Roughly, the method is:

  1. Collect the data in Flash using a SWF file embedded in a Qualtrics survey question.
  2. Call a JavaScript function (stored in the same HTML page) from inside of the SWF file, and pass the collected data to this function.
  3. Use the JavaScript function to store the received data as an Embedded Data object in the Qualtrics survey flow.
  4. Download your data from Qualtrics’ Survey Results page.

Compare this to the Flash-XML-PHP route:

  1. Collect the data in Flash using a SWF file embedded in an HTML (or PHP) webpage.
  2. In the SWF file, turn the data into an XML object, and pass the XML object from the SWF file to the PHP script (a separate file) using an HTTPRequest and “POST” or “GET.”
  3. Use the PHP script to parse the XML object and write a CSV file with the data to store on the server.
  4. Download your data from the server.

Both methods require a bit of setup time, effort, and debugging. The main advantage of the ExternalInterface-Javascript method is that we can use it in situations where we can’t use PHP and/or do not have permission to create new files on the server. (As mentioned, MTurk is another service with these restrictions that comes to mind.)

The XML-PHP method has its own benefits, especially if you already host surveys on your own server, and/or use PHP regularly to customize how the data is stored before you download it. In this case, however, I wanted to add Flash tasks to a survey with non-Flash questions, and the non-Flash questions are easier to build and maintain within the Qualtrics survey framework, than the custom forms I would have built on a private server.

So, in order to implement this method we have to:

  • In Flash, import objects that allow for outside communication.
  • In Flash, add code to actually send data out using the ExternalInterface object.
  • In Qualtrics, embed the Flash file in a survey question (in a way that allows Flash to communicate with JavaScript).
  • In Qualtrics, code the JavaScript function that will be called by the Flash file, and will store the data as an Embedded Data object in Qualtrics.
  • Finally, test and double-check (read: debug) everything.

Let’s get started!

Building Flash Programs that Export Data via ExternalInterface

First, we need code to let us use ExternalInterface’s functions:

import flash.external.ExternalInterface;
flash.system.Security.allowDomain("cmu.qualtrics.com");
flash.system.Security.allowDomain("jfe.qualtrics.com");
flash.system.Security.allowDomain("s.qualtrics.com");

To use the ExternalInterface object (specifically the function call() ), you’ll need to load it in the beginning of your AS3 code, using the import flash.external.ExternalInterface; command. The next three lines calling allowDomain() allow communication between where the SWF file is hosted and each of three domains. Since I am at CMU, cmu.qualtrics.com is where most of my surveys are hosted, jfe.qualtrics.com is the standard qualtrics server where any remaining surveys are hosted, and s.qualtrics.com is where I noticed my Library files (e.g., my Flash SWF files) are hosted. By using allowDomain(“domain name”), I am telling my SWF to play nice with information going to and from all three of these locations.

Be careful: The default is not to have any connections between Flash and outside domains, because each outside connection reduces information security. Put another way, we are increasing the security risk with each domain we say it is okay for Flash to talk to. Don’t add domains haphazardly, and do your own additional reading about security measures if you collect particularly sensitive information.

Next, we need Flash/ActionScript 3 code that sends the data our SWF file has collected. Somewhere in your FLA or AS3 files (say, the very end), you’ll need some like the following:

/////////////////////////////////////////////////////////////////////
// AS3 ExternalInterface/Javascript exporting code

if(ExternalInterface.available) {
try { ExternalInterface.call("jsFunctionName",parameters);
} catch (error:Error) {
// trace("Error.");
} catch (error:SecurityError) {
// trace("Security error.");
}
} else {
// trace("ExternalInterface not available.");
}

While you are debugging, make sure to put descriptive error messages in the appropriate places so you know exactly when (and where) any problems occurred. For example, use trace() when you’re debugging the FLA, and something that outputs to the screen when you’re debugging the SWF in the browser. For example, I usually output error messages in a text field on the Stage (e.g., myTextField.text = “ExternalInterface not available.”;), so I can seen them when I switch to debugging in my browser. Then I comment out that line of code for the final version of my SWF file.

Deciding how to format the data when you send it is completely your choice. You can pass as many (or as few) arguments as desired to your JavaScript function. Above, I wrote:

ExternalInterface.call("jsFunctionName",parameters);

but I could have used:

ExternalInterface.call("jsFunctionName",parameter1,parameter2,parameter3);

or even sent no arguments and just called the function:

ExternalInterface.call("jsFunctionName");

The simple approach I’m showing here is to pass one argument: a string of comma-separated reaction time data. After data collection, I’ll use a string splitting function in my data analysis tool of choice (R) to put everything into a nice table of observations.

I’m taking this approach until I find the time build a function that automatically creates an Embedded Data object for every argument sent to the JavaScript function. Baby steps.

Embedding Flash in Qualtrics

Now, on the Qualtrics side, let’s start by putting the SWF file into a standard question. Make a new graphics/descriptive text question type (instructions). Then, edit its text, but make sure to switch into the “HTML View” mode (a tab in the upper right corner of the Edit Question box) when copy-and-pasting the code below.

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="###" height="###" id="taskname" align="middle">
    <param name="movie" value="https://s.qualtrics.com/ControlPanel/File.php?F=ALPHABETSOUPHERE" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffffff" />
    <param name="play" value="true" />
    <param name="loop" value="true" />
    <param name="wmode" value="window" />
    <param name="scale" value="showall" />
    <param name="menu" value="true" />
    <param name="devicefont" value="false" />
    <param name="salign" value="" />
    <param name="allowScriptAccess" value="always" />

    <object type="application/x-shockwave-flash" data="https://s.qualtrics.com/ControlPanel/File.php?F=ALPHABETSOUPHERE" width="###" height="###">
      <param name="movie" value="https://s.qualtrics.com/ControlPanel/File.php?F=ALPHABETSOUPHERE" />
      <param name="quality" value="high" />
      <param name="bgcolor" value="#ffffff" />
      <param name="play" value="true" />
      <param name="loop" value="true" />
      <param name="wmode" value="window" />
      <param name="scale" value="showall" />
      <param name="menu" value="true" />
      <param name="devicefont" value="false" />
      <param name="salign" value="" />
      <param name="allowScriptAccess" value="always" />

      <a href="http://www.adobe.com/go/getflash">
        <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
      </a>

    </object>

</object>

Yes, there are a lot of parameters up there. In the first <object … > tag you’ll need to edit:

  • width=”###”
  • height=”###”
  • id=”taskname”

Then, you’ll need to get the address of the SWF file you uploaded to Qualtrics (instructions), and put that in the the locations that say:

value="https://s.qualtrics.com/ControlPanel/File.php?F=ALPHABETSOUPHERE"

Finally, you need to make sure that your “allowScriptAccess” parameter is set to “always” — if we were using just one domain (remember those initial three lines in the Flash code?), then “sameDomain” might be possible, but in this case, use “always”.

Using JavaScript to Receive and Store the Data

Finally, let’s create the JavaScript function our Flash file wants to talk to. We’re going to put the following code in the survey’s header, in the”Advanced” tab of the “Look and Feel” section (more instructions here). By putting this

<script type="text/javascript">
  //alert("The in-question script is recognized."); // for debugging
  //Qualtrics.SurveyEngine.setEmbeddedData("flashStorage","No data stored (1)"); // for doublechecking setEmbeddedData

  function receiveFlashStorage(swfName,receiveStorageInfo) {
    //alert("Received data from "+swfName); // for debugging

    switch(swfName) {
      case "task1name":
        Qualtrics.SurveyEngine.setEmbeddedData("task1FlashData",receiveStorageInfo);
        //document.getElementById("demo").innerHTML = "task1FlashData: "+receiveStorageInfo; // for debugging
        break;
      case "task2name":
        Qualtrics.SurveyEngine.setEmbeddedData("task2FlashData",receiveStorageInfo);
        //document.getElementById("demo").innerHTML = "task2FlashData: "+receiveStorageInfo;
        break;
      default:
        Qualtrics.SurveyEngine.setEmbeddedData("flashStorage","No data stored (SWF name was default.)");
    }

    $('NextButton').setValue("  ( >> )  "); 
    $('NextButton').setAttribute("style", "");
  }
</script>

Here, my JavaScript code uses the

switch (variable) {
    case "value":
    //...
    break;
}

condition structure to check for the name of the task that sent the information, and then store the data passed along in the appropriate Embedded Data object.

The code also has multiple commented out debugging methods: alert() outputs to the screen, and the setEmbeddedData calls store messages in Qualtrics.

[Note: the original version of this method repeated the same JavaScript function code in the HTML of every SWF-containing question. Putting this  into the survey header makes it accessible on every page, without the added copy and pasting.]

Setting up Qualtrics to receive the data

And here is the final step: create an embedded data object for your JavaScript function to drop the data into. Technically the Qualtrics JavaScript API has a function that can create new Embedded Data objects, but it doesn’t work with this code yet . One strong reason is because the JavaScript is outside of the Qualtrics-designated JavaScript zone, but I’ve had buggy experiences with that particular function inside of the proper scripting area, so I tend to create Embedded Data objects manually regardless.

Qualtrics has a tutorial on creating Embedded Data. Make sure:

  • The name of your object is exactly the same as the name your setEmbeddedData() function is looking for (you must even match upper- and lowercase letters).
  • The Embedded Data object is created by the Survey Flow before your question (with the JavaScript embedded SWF file) is ever shown to a survey-taker.

Bonus: Hiding Qualtrics’ continue button until finished

You may have noticed the JavaScript code placed into the survey’s header included these two lines at the end:

    $('NextButton').setValue("  ( >> )  "); 
    $('NextButton').setAttribute("style", "");

The code I’ve shown here stores data from the Flash program after the rest of the program has finished. This means we want participants to interact and finish interacting with the Flash program before they move onto the next question in Qualtrics.

With normal Qualtrics questions, you can select “Force Response” or “Request Response” to make sure participants have chosen an answer before they continue, but no such option is available when using the Graphics/Text question type. So, I use Javascript to hide the continue (>>) button, until after the Flash program has stored its data.

Alternatively, you could just have the Flash SWF call your storage function every time it received new data, and modify the storage code to append this new data to the appropriate Embedded Data object. Such a method might be more appropriate if you want to collect partial data (either for analysis, or to remember how much of a task a participant has completed), as it could store data as a partial response even if participants close their browser window. The method shown here has no such partial storage ability.

Those two lines of code in the storage function are what return the continue button to its original state (visible, and showing “(>>)”.

The lines of code that hide the continue button in the first place are the following:

	$('NextButton').setValue(" "); //} 
	$('NextButton').setAttribute("style", "display:none");

These need to be placed in the JavaScript editor section specifically for the question containing the SWF (the question where we added the <object …>…</object> code in HTML mode).

Make sure to debug this addition especially, because if something goes wrong, your participants won’t be able to move forward in your survey (or they’ll be able to move forward without interacting with your Flash program).

References:

Simcox, T., & Fiez, J. A. (2013). Collecting response times using Amazon Mechanical Turk and Adobe Flash. Behavior Research Methods. doi:10.3758/s13428-013-0345-y

2 thoughts on “Collecting Data with Flash in Qualtrics, via Javascript

    1. Thank you, Jeff! Let me know how it goes. I think the method should hold up across a variety of browser types, but only time and testing will tell.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>