Qualtrics

With Qualtrics and FullStory working together, you can add FullStory session URLs to survey responses and pass survey responses into FullStory. Additionally, FullStory Ragehooks allow you to detect frustrated sessions and automatically send surveys. This bi-directional flow of data allows you to:

  • Quickly search for and segment users based on positive or negative feedback in order to understand how their  experience affected their survey response
  • Expose the relationship between your Qualtrics response data and your conversion rates and uncover revenue-impacting improvements.
  • Deliver targeted surveys to frustrated customers in a timely and relevant manner.
  • Laser in on sessions where a user left specific feedback, a low NPS score, or any other response data and get a full view of their experience.
  • … and more

Connecting the two products currently requires some manual configuration of your survey and your site intercepts. Note that all examples below are for the JFE survey engine, not the SE engine.

Step 1: Pass FullStory data into surveys

Using Website / App Feedback projects

If you have access to Website / App Feedback projects in Qualtrics, you can use intercepts to automatically pass information into FullStory when a survey is launched. Intercepts serve as the glue between your survey and your website, and they are highly configurable. The steps below will show how to use embedded data to pass FullStory data points into the survey. 

  1. Open your intercept and configure the intercept behavior until you reach the Embedded Data step.
  2. Create three pieces of embedded data: fsCookie, fsSession, and fsSessionUrl, as shown in the screenshot below:Screen_Shot_2022-04-14_at_1.21.01_PM.png
  3. The fsCookie field should get its value from a cookie named “fs_uid”.
  4. The other two embedded data fields are JavaScript values. The value for fsSession should be as follows:
    • window["_fs_namespace"] && window[window["_fs_namespace"]] && window[window["_fs_namespace"]].getCurrentSession ? window[window["_fs_namespace"]].getCurrentSession() : ""
  5. The value for fsSessionUrl should be as follows:
    • window["_fs_namespace"] && window[window["_fs_namespace"]] && window[window["_fs_namespace"]].getCurrentSessionURL ? window[window["_fs_namespace"]].getCurrentSessionURL() + "?integration_src=qualtrics" : ""
  6. Click “Save,” and then publish the intercept.

Without Website / App Feedback projects

If your Qualtrics plan does not include Website / App Feedback projects, but you have built your own mechanism for launching surveys from your website, you can still integrate Qualtrics and FullStory. Note that, because FullStory only runs on your website, integration is only possible if you are somehow distributing surveys from your website and can make calls to FullStory’s client API.

Embedded data fields are passed into the survey as part of the survey URL. In the absence of site intercepts, you can simply construct the appropriate survey URL yourself.

You will need to add one parameter to the survey URL for each embedded data field. The final URL should be of the form:

 [survey-url]?fsSession=[sessionId]&fsSessionUrl=[sessionUrl]&fsCookie=[cookie]

Here is a more complete example; note that the parameter values have been URL-encoded:

https://yourdomain.iad1.qualtrics.com/jfe/form/SV_yourformid?fsSession=5035086660665344%3A5926679935680512&fsSessionUrl=https%3A%2F%2Fapp.fullstory.com%2Fui%2FABC123%2Fsession%2F5035086660665344%253A5926679935680512&fsCookie=rs.fullstory.com%23ABC123%235035086660665344%3A5926679935680512%234cc0a823%23%2F1603489634

Parameter values:

  • fsSession - The result of a call to FS.getCurrentSession.
  • fsSessionUrl - The result of a call to FS.getCurrentSessionUrl + "?integration_src=qualtrics"
  • fsCookie - The value of a cookie named fs_uid. Note that FullStory only uses first-party cookies, so the cookie value should be fully accessible.

Step 2: Configure survey capture

The next step is to configure the survey to capture activity into the same FullStory session from which the survey was launched. 

Set up incoming embedded data

Open your survey project, and then open the survey flow. At the start of the flow, if you don’t already have an embedded data block, add one. Add fields for fsCookie, fsSession, and fsSessionUrl, without setting a value (their values will thus be taken from the survey URL). 

image7.png

FullStory session IDs and URLs will now appear in the embedded data section of survey responses. 

The FullStory cookie will also appear, but the cookie has no value by itself. In the next section, we will see how to set up capturing of surveys, and how to use the cookie to tie together survey activity with data capture on your website.

Add data capture JavaScript

JFE surveys are single-page apps, so capturing the survey can be accomplished by adding the FullStory snippet to the first question of your survey. On the first question, click the Edit Question side panel on the left. Click the Javascript option that appears in the Question behavior section of the side panel.

Image_2022-07-25_at_9.00.39_AM.jpg

In the below snippet, replace “[YOUR SNIPPET HERE]” with your FullStory snippet. If you have no other JavaScript logic on the question, you can copy-paste the entire snippet into the pop-up window. If you have existing logic in the addOnload function, add the content of the function to your existing function content:

Qualtrics.SurveyEngine.addOnload(function () {
  try {
    var sessionUrl = '${e://Field/fsSessionUrl}';
    var embeddedCookie = '${e://Field/fsCookie}';

    if (sessionUrl) {
    // PopOver or Slider runs in iframe and can use parent window's snippet
    window['_fs_run_in_iframe'] = window.self !== window.top;

      // new or embedded window requires setting the fs_uid cookie manually
      if (!window['_fs_run_in_iframe'] && embeddedCookie) {
        var nowInSeconds = Math.floor(Date.now() / 1000);
        var maxExpiration = nowInSeconds + 31536000;
        var tokens = embeddedCookie.split("/");
        var content = tokens[0];
        var maybeExpiration = tokens[1];
        var expiration = parseInt(maybeExpiration);
        if (expiration > maxExpiration) { expiration = maxExpiration; }

        var newCookie = 'fs_uid=' + content + '/' + expiration;
        newCookie += '; domain=.qualtrics.com; Expires=' + expiration
        newCookie += '; path=/; SameSite=Strict; Secure';                               
        document.cookie = newCookie;
      }

    // FS snippet without the <script> tags
    [YOUR SNIPPET HERE]
    }
  } catch (err) {
    console.warn(err.message);
  }
});

 

This logic extracts the FullStory cookie from the embedded data and sets the cookie on the Qualtrics domain. It then runs the FullStory snippet to start capturing the survey. The cookie is sent along with captured data, so its value can be used on FullStory servers to stitch together activity on your website domain with survey activity on the Qualtrics domain.

Step 3: Pass survey results into FullStory

Now that surveys are being captured, the FullStory client API will be available on the survey. We can use custom variables and/or custom events to send values from survey responses into FullStory. 

The below snippet is an example of submitting the user’s NPS to FullStory when it is the last question in a survey. It is the JavaScript snippet on the NPS question itself, so `this` in the code refers to the NPS question object. This example makes use of both custom variables and custom events, so that you can search for a user based on their score and for sessions during which they submitted the score.

Qualtrics.SurveyEngine.addOnPageSubmit(function(type) {
// This is the last page, so submit a custom event for the survey with the NPS score
if(type == 'next') {
let eventProps = {};
let selected = this.getSelectedChoices();
if (selected.length > 0) {
let nps = parseInt(selected[0]);
eventProps.nps_real = nps;
eventProps.isDetractor_bool = nps <= 6;
eventProps.isPromoter_bool = nps >= 9;
eventProps.isPassive_bool = nps > 6 && nps < 9;
switch(nps) {
case 10:
case 9:
eventProps.npsGroup_str = 'Promoter';
break;
case 8:
case 7:
eventProps.npsGroup_str = 'Passive';
break;
default:
eventProps.npsGroup_str = 'Detractor';
}
}
                
// TODO: you could add answers to other questions that are of interest, for cohorting
     
FS.event('Qualtrics CSAT Submitted', eventProps, 'qualtrics');
FS.setUserVars(eventProps, 'qualtrics');
}
});

Note that because this is a question on a page which has not yet been submitted, you cannot use piped text to fetch the answer value. Piped text could be used for the answers to questions on previous pages in the survey flow, and it would considerably simplify the above example. 

This example shows how to retrieve the answer to a Net Promoter Score question; refer to the Qualtrics Question API for examples of working with answer values to different types of questions.

FullStory + Qualtrics Widget

If you'd like to watch FullStory sessions within your Qualtrics dashboard, you have the option to have these directly embedded into Qualtrics. This allows you to view relevant information from both platforms in one place.

Follow the steps below to embed your Session Replay Widget into your Qualtrics dashboard.

Note: Only Admin level users in Qualtrics are capable of enabling the Session Replay widget. They can however allow all users of the Qualtrics account to add to their personal dashboards after initial setup.

You'll need to have the extension enabled in your Qualtrics account by filling out this form - https://devdemos.qualtrics.com/jfe/form/SV_5tlR5aDkLiNjYh0. Once the extension has been added to the brand's instance, an Admin will need to install it. From the horizontal line menu at the top left of your screen, select Admin > Extensions.

  1. To start, ensure you are logged into Qualtrics and then navigate to the dashboard you wish to add the widget to.
  2. Click Edit Page at the top right of your dashboard
    qualtrics_edit_page.png
  3. Click +Add Widget at the bottom of the dashboard
    qualtrics_add_widget.png
  4. Select FullStory Session Replay from the bottom of the widget table
    Screen_Shot_2022-08-15_at_9.06.47_AM.png
  5. Give your widget a Title and check the Show number of responses checkbox for better visibility into the feedback you are receiving and tracking
    Screen_Shot_2022-07-15_at_3.27.40_PM.png
  6. Next, select the FullStory account you wish to connect. If you haven't connected one yet, click Add user account.
    Screen_Shot_2022-07-15_at_3.30.24_PM.png
    Give it a name and enter your API token. Then click Connect account.
    Screen_Shot_2022-07-15_at_3.30.37_PM.png
    Once your account has been created, click next.
    Screen_Shot_2022-07-15_at_3.30.47_PM.png
  7. After your account is selected, you can begin selecting from the drop down menus on the right hand side to fill in your Date, Text, Score and Session URL Fields. Click Done when finished.
    • For the Date field, select Recorded Date
    • For the Text field, select a question that is meaningful to the data you are tracking (for example: NPS related question)
    • For Score field, select a numeric value that you are tracking, related to the previous Text field
    • Under Session URL, select Embedded Data - fsSessionUrl
      Screen_Shot_2022-07-15_at_4.00.58_PM.png
  8. To save your work, click Done Editing at the top of your dashboard
    Screen_Shot_2022-07-15_at_4.09.27_PM.png
  9. You'll want to make sure that you expand the size of the embed widget to fit the session replay data that will soon appear. If you see the following message, you'll know to enlarge the widget. To do so, just click Edit Page at the top of your dashboard and adjust accordingly:
    To view this Session and all of its related information, you'll need to resize this container to make it bigger. Alternatively, you can view this Session Replay directly in FullStory by clicking the button below.
    CleanShot_2022-09-20_at_11.31.04_2x.png

Next, if you'd like other users of your Qualtrics account to be able to add the Session Replay widget to their personal dashboards, you'll need to first share this with them by following the below steps.

  1. Click on the Main Menu icon in the top left of your account and select Admin
    qualtrics_admin.png
  2. On the following page, click Extensions
    Screen_Shot_2022-07-15_at_4.14.05_PM.png
  3. Find and click on the FullStory extension on the next page
    Screen_Shot_2022-08-24_at_11.17.59_AM.png
  4. Next, under your API key that you previously entered in the above instructions, click Manage Access
    qualtrics_manage_api_access.png
  5. Click the Users tab and then click Give access to all users
    qualtrics_give_access_to_all_users.png

Note: An additional step is required to load the session replay widget on FireFox browsers. When loading the session replay widget for the first time, the message below will be displayed. Please click “Allow” and accept the browser prompt. This allows the session replay to access Local Storage, thus registering ServiceWorkers in order to provide the session replay service. After granting access, the session replay iframe will refresh and load the corresponding session.

Screen_Shot_2022-08-16_at_3.45.58_PM.pngScreen_Shot_2022-08-16_at_3.46.06_PM.png

Additional Options

Intercept displayed custom event (optional)

Qualtrics keeps statistics that allow you to calculate click-through rates for your intercepts, but you may want to do similar or related analyses in FullStory. You can capture the display of an intercept by adding JavaScript to your intercept as in the example below: 

image4.png

You could then use the FullStory Conversions functionality to view click-through rates for your survey:

Screen_Shot_2022-07-11_at_12.22.35_PM.pngScreen_Shot_2022-07-11_at_12.22.57_PM.png

Manual deployment (optional)

Note: If you are already using a tag manager or CDP to deploy FullStory, you don’t need to do the below steps.

If you are not using a tag manager like GTM or a CDP like Segment or Tealium, you may wish to manually ensure that there are no load timing issues between FullStory and your Qualtrics intercept. The below steps ensure that the intercept loads after capturing starts, so that FullStory session URLs are available to the Qualtrics intercept.

Configure your intercept for manual deployment by following the instructions at “Implementing Manually with JavaScript API.” This means that you will need additional JavaScript code in your web application to load the intercept and evaluate whether it should be displayed to the end user.

This additional JavaScript code is provided by the FullStory integration with Qualtrics. To get started, navigate to Settings > Integrations > Manage. Next to the Qualtrics integration, click the “Add” button.

FullStory_2022-04-22_at_12.59.44_PM.jpg

When installation is complete, the integration configuration window will slide out from the right side. Click “Done.”

FullStory_2022-04-22_at_11.47.29_AM.jpg

Ragehooks for Qualtrics

Using FullStory Ragehooks and Qualtrics Website Feedback or JSON events, you can leverage frustrated session information with Qualtrics. This information can be used to display a prompt for feedback at the moment of frustration or with event-based actions to start any number of tasks within Qualtrics.

Displaying the Website Feedback prompt

A convenient way to obtain feedback is using the Qualtrics Website Feedback prompt that is already deployed on your website.  FullStory Ragehooks can launch the feedback prompt after a configurable number of frustration events have occurred.

Similar to adding the FullStory snippet to your site, add the following Ragehook for Qualtrics Website Feedback snippet. The Ragehook snippet has no dependency on the snippet, but if you’d like to include it near it or other FullStory integrations, that’ll keep everything organized.

var _fs_qualtrics_frustration_intercept = (function (exports) {
  'use strict';

  // TODO decide when you want to launch the intercept
  var threshold = 0; // send when a threshold has been met or is above
  // number of frustration events for the current page
  var counter = 0;
  /**
   * Adds frustration event listeners.
   */
  function addEventListeners() {
    ['fullstory/rageclick'].forEach(function (event) {
      window.addEventListener(event, launchIntercept);
    });
  }
  /**
   * Launches the Intercept currently configured on the page.
   */
  function launchIntercept() {
    var feedbackButton = document.querySelector('#QSIFeedbackButton-btn');
    // NOTE only a single rage event will trigger the intercept in a browser session
    if (feedbackButton && counter >= threshold && !sessionStorage.getItem('_fs_xmInterceptShown')) {
      feedbackButton.click();
      sessionStorage.setItem('_fs_xmInterceptShown', 'true');
counter++; } } function run() { addEventListeners(); } exports.addEventListeners = addEventListeners; exports.launchIntercept = launchIntercept; exports.run = run; return exports; }({})); _fs_qualtrics_frustration_intercept.run();

Depending on when you'd like to show the Website Feedback prompt:

  • Change the threshold variable if you’d like to display the prompt only when the user exceeds some predefined number of frustration events. By default, it will display on the first frustration event.

Sending email surveys

An alternative to Website Feedback is sending an email survey using an event-based action and email task.  Sending email surveys to frustrated customers has three parts:

  1. Create an event-based action and email task in Qualtrics.
  2. Host a bit of code that executes on a server. This uses a Qualtrics API token and should not be used client-side.
  3. Add client-side code to your website that leverages FullStory Ragehooks for Qualtrics JSON Events and sends information to your server-side program.

Create an event-based action and task

Start by generating an API token if you have not done so previously.

Next, visit the Actions page in Qualtrics and click Create an action. Choose event-based from the dropdown. Then click choose event and select the JSON Event tile. Use the Copy URL button to copy the url to the clipboard, it will be used in the subsequent section.

Next, follow instructions to deploy the server-side and client-side code. You’ll return to the action dialog after deployment.

Deploy the server-side code

In order to send JSON events to Qualtrics, an API token must be used. Since this is like a password, it should not be placed in any code that may appear in the browser. A small program can be hosted to create the JSON event while securely storing your API token.

Below is a sample server that uses Express to create such a program; Qualtrics also provides a similar example. Your IT department or developers may already have ways to integrate with Qualtrics, so check with them first before writing your own solution.

  1. Perform the following changes to start the server:
    Update the text <VALUE_FROM_COPY_URL> with the Copy URL text from your clipboard.
  2. Either set an environment variable called apiToken with your Qualtrics API token or change the code const { apiToken } = process.env; to include your token.
  3. Deploy or start the server locally using node qualtrics-proxy.js. You’ll need Node.js to do this.
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const request = require('request-promise');

// a map of event types to action endpoints
// see https://www.qualtrics.com/support/survey-platform/actions-module/json-events/#SettingUp
const eventEndpoints = {
  'fullstory/rageclick': '<YOUR_ACTION_URL>'
};

// https://www.qualtrics.com/support/survey-platform/actions-module/json-events/#Example
async function createEvent(payload) {
  const { apiToken } = process.env;

  if (!apiToken) {
    throw new Error('Qualtrics apiToken is not defined');
  }

  const { type } = payload;
  const url = eventEndpoints[type];

  if (!url) {
    throw new Error(`Failed to map FullStory frustration event to Qualtrics JSON Event URL`);
  } else {
    console.log(`Sending JSON event to ${url}`);

    return await request.post({
      url,
      json: true,
      body: payload,
      headers: {
        'Content-Type': 'application/json',
        'X-API-TOKEN': apiToken
      }
    });
  }
}

// create a simple Express server to handle POST from browser
const app = express();
app.use(bodyParser.json());
app.use(cors());
app.post('/jsonevent', async (req, res) => {
  console.log(`JSON event received\n${JSON.stringify(req.body, null, 2)}`);

  try {
    const response = await createEvent(req.body);
    console.log(`Qualtrics returned\n${JSON.stringify(response, null, 2)}`);

    res.sendStatus(200);
  } catch (err) {
    res.sendStatus(500);
  }
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Qualtrics proxy listening on ${port}`);
});

Adding the Ragehook snippet

Similar to adding the FullStory snippet to your site, add the following Ragehook for Qualtrics JSON Events snippet. The Ragehook snippet has no dependency on the snippet, but if you’d like to include it near it or other FullStory integrations, that’ll keep everything organized.

var _fs_qualtrics_frustration = (function (exports) {
 'use strict';

 // Server-side sample endpoint (note this is your proxy code and not Qualtrics)
 var proxyEndpoint = '';
 // TODO decide when you want to send frustration events to Qualtrics
 var threshold = 0; // send when a threshold has been met or is above
 // number of frustration events for the current page
 var counter = 0;
 /**
  * Adds frustration event listeners.
  */
 function addEventListeners() {
  ['fullstory/rageclick'].forEach(function (event) {
   window.addEventListener(event, postFrustrationEvent);
  });
 }
 /**
  * To send a survey, you'll need to provide the following details about the user:
  * - First name
  * - Last name
  * - email address
  * If you use a XM Directory task, prevent multiple contacts from being added to
  * XM Directory, by enabling deduplication on the email address.
  */
 function getUser() {
  return {
   firsName: '<YOUR_USERS_FIRST_NAME>',
   lastName: '<YOUR_USERS_LAST_NAME>',
   email: '<YOUR_USERS_EMAIL>'
  };
 }
 /**
  * Sends the frustration event to the Qualtrics proxy sample.
  * @param event the browser's CustomEvent emitted by FullStory
  * @param url to the Qualtrics server-side code
  */
 function postFrustrationEvent(event, url) {
  if (url === void 0) { url = proxyEndpoint; }
  var type = event.type;
  var _a = event.detail,
   eventEndTimeStamp = _a.eventEndTimeStamp,
   eventReplayUrlAtCurrentTime = _a.eventReplayUrlAtCurrentTime,
   eventReplayUrlAtStart = _a.eventReplayUrlAtStart,
   eventStartTimeStamp = _a.eventStartTimeStamp;

  counter++;
  // create the json event payload using info from the ragehook
  var body = {
   type: type,
   eventEndTimeStamp: eventEndTimeStamp,
   eventReplayUrlAtCurrentTime: eventReplayUrlAtCurrentTime,
   eventReplayUrlAtStart: eventReplayUrlAtStart,
   eventStartTimeStamp: eventStartTimeStamp,
  };
  // a user should be present
  var user = getUser();
  if (user) {
   body.firstName = user.firsName;
   body.lastName = user.lastName;
   body.email = user.email;
  }
  else {
   console.warn("Unable to send survey because user information is missing");
  }
  // only a single rage event will be sent for the current browser session
  if (counter >= threshold &&
   sessionStorage.getItem('_fs_xmEventSeen') !== type) {
   var request = new XMLHttpRequest();
   request.open('POST', url);
   request.setRequestHeader('Content-type', 'application/json');
   request.send(JSON.stringify(body));
   sessionStorage.setItem('_fs_xmEventSeen', type);
  }
 }
 function run() {
  addEventListeners();
 }

 exports.addEventListeners = addEventListeners;
 exports.getUser = getUser;
 exports.postFrustrationEvent = postFrustrationEvent;
 exports.run = run;

 return exports;

}({}));

_fs_qualtrics_frustration.run();

You’ll want to make a few adjustments to the snippet:

  • Update the proxyEndpoint variable so that it matches your server’s endpoint running the server-side code. This will vary depending on how you’ve hosted the server-side program. If you’re using the sample locally, the value is http://localhost:3000/jsonevent.
  • Change the threshold variable if you’d like to send surveys only when the user exceeds some predefined number of frustration events. By default, it will send the JSON event on the first event.
  • Implement the getUser() function based on your website. If you’re just testing, you can manually fill in your personal information.

Capture event data

With the server-side and client-side code deployed, return to the action dialog, which is still Waiting for an event to be fired. (If it does not say this, simply refresh the page.)

From your website that now has the Ragehook snippet, click furiously on some white space or text. This will trigger the Ragehook and will send a JSON event to Qualtrics. The actions dialog will momentarily show the contents of the JSON event.

actiondialog.png

Click Finish, then select Add Task, and select the XM Directory tile. Select Distribute survey and fill out the corresponding details:

surveoptions1.png

surveoptions2.png

 

There are a few things to point out in the above settings:

  • See Qualtrics help documentation more details on XM Directory.
  • The survey is immediately sent. If you’d rather delay, use the Schedule a time option.
  • Since these are “frustrated users”, they are being added to a specific contact list called Frustrated Visitors. You can choose to add these to an existing contact list if you’d like.
  • Each time the customer sends a frustration event to Qualtrics, it will be captured as a transaction to the contact info. If this is the customer’s first event, a new contact will be added to the list.  Visit Qualtics help documentation for more about transactional data.

Click Save and update the title to something descriptive. Finally, toggle the action to On to complete the integration.

Close your browser window and open a new one. Rage clicking will trigger a survey to be delivered. Congratulations, you’ve now set up an automated survey solution for your most frustrated customers.

One final note: the client-side code will send the JSON event only once during a customer’s visit. If the user returns to your site some time later, it will send another event. Qualtrics will temporarily recognize the user’s email address and prevent re-sending a previously sent survey (see "Skipped as Duplicate in Email Distribution Error Messages). To be certain that users do not receive unnecessary surveys as a result of Ragehook integration, update the server side code to include additional behavior to store previous interactions with site visitors. 

duplicate.png

Need to get in touch with us?

The FullStory Team awaits your every question.

Ask the Community Technical Support