XM Solution Deep Dive
Objectives
This guide helps you:
- Learn details about the structure and purpose of XM Solution Plugins.
- Build and Interact with an XM Solution Plugin.
If you would like to join the early access program for XM Solution Plugins, then please let us know by taking this survey.
This feature is in Early Access and is not yet generally available. Functionality, APIs, and documentation may change before general availability.
Prerequisites
Before continuing with this guide we recommend that you review and complete these guides:
What is an XM Solution?
The most basic version of an XM Solution is a template of a Qualtrics project. It allows you to save a project configuration so that any user could recreate it in their own account. This can be useful if you find yourself recreating similar projects many times.
XM Solutions can be more complex than a simple template. You can also collect user input and customize the template for the user automatically.
For example, you might be creating a project that measures the perception of certain products and includes a survey and dashboard. This project might be very similar every time, but the products being tested will be different for different users or different points in time.
If you use an XM Solution, you can have the users tell you which products they're testing and automatically build out the project accordingly.
Limitations
XM Solutions do not currently integrate with everything Qualtrics has to offer. To see if they are currently capable of your desired use case, check out our list of currently supported resources here.
Process for creating an XM Solution
Step 1: Make a working Qualtrics project
To make an XM Solution, start with a working Qualtrics project that has already been created and finalized. Our best practice recommendation is to finalize as much as possible before you begin turning your project into an XM Solution.
Make sure you're not expecting any more changes in resources like surveys and dashboards. It is possible, but more difficult, to make changes to the content after you start integrating it into an XM Solution.
Additionally, the starting project should contain everything a user of the XM Solution might ever see. It is generally much easier to remove things like optional survey questions than it is to create content from scratch later.
Step 2: Start with a working template
Get a very simple solution working before trying to pull in more resources or add more customization. For a detailed guide on how to get a solution working, follow the Quickstart guide.
When you initialize your Plugin, you should choose the template that most closely matches your use case. If you are experienced in creating XM Solutions, then you may want to choose the blank template instead.
Before moving on, you should have an XM Solution that is visible in the Catalog and can be created without errors. Now, when you make changes, you will be able to see how and if they work right away.
You may also want to take some time at this point to customize how it looks in the Catalog. That way your XM Solution will be easy to find as you build and test it.
Edit the src/catalogConfig.json file to customize the name, description and icons associated with your XM Solution. For full details on how to customize its appearance in the Catalog check out the full reference here.
Step 3: Make a static version of your XM Solution
Now that you have a working starting point, you are going to replace the resources from the template with the resources you would actually like to build. Resources represent a piece of Qualtrics functionality like a survey or dashboard.
By default, these resources are located in the src/Resources directory, but you can move them around as long as you keep them under the src directory.
Import resources
To start creating a solution, you'll likely want to import a project. You can do this by running solution import in your Plugin directory.
By default, the import command will not delete any of your resource files. If you prefer to delete everything and start fresh, you can run the command with the replace flag.
solution import --replace or solution import -r
It will ask you to choose a resource type to import. Currently, the Solution CLI can import a Survey project or a CX Dashboard project.
After making a selection, it will ask you to select a project type, which vary between resource types. If you're not sure what the project type is, you can see information about the different types of projects here.
In the screenshot below, you can see that the "Make me into a Solution" project has the type Customer Satisfaction (CSAT).

Finally, you'll be presented with a list of projects of the specified resource type and project type that you have access to.
Once you select the project you would like to import, the CLI will download the specified resource along with all of its dependencies, a generic transformation file, a placeholder Setup Assistant file, and a complete Solution Execution file.
All downloaded resources will be placed into a folder named something like "Resources_ab12" except the Solution Execution file which will be placed in the "src" folder and named "solutionExecution_ab12.json".
The suffix will be different each time you run the import command, so you can freely import as many times as you'd like without fear of losing work.
To use these resources, you simply need to rename "solutionExecution_ab12.json" to "solutionExecution.json". Then, you
can run solution build, submit your extension, and you should have a fully functioning solution!
You can now run solution validate (after running solution generate-test if you haven't done so already) to do a dry run of all the steps in
your Solution Execution file.
solution import command with replace flag-
The downloaded Solution Execution file will be named as solutionExecution.json, replacing the original Solution Execution File
-
All original resource files will be removed from the /src directory replacing by the downloaded resources in a unique folder like Resource_ab12.
-
After importing with the
replaceflag, the imported resources should be working (buildandvalidate) without any additional editing.
Eventually, you'll need to go in and customize your solution by creating a real Setup Assistant file, more tailored transformation files, etc. You'll learn more about how to do so later.
Modify the framework to create your resources
The resources you downloaded in the last step are going to be used as templates to create copies of those resources for the users using your XM Solution. You need to orchestrate this creation using the Solution Execution file (src/solutionExecution.json).
This file is mostly a list of steps that you want your XM Solution to execute. For now, just add or replace an existing "Create" step for each of your resources. Those steps will look something like this:
{
"id": "trigger",
"type": "Create",
"config": {
"apiVersion": "survey.v0",
"templateFilePath": "Resources/survey.qsf",
"transformationFilePath": "Resources/modifySurvey.js"
}
},
It's important that the value of type is Create, and that the value of the key templateFilePath is the path to your resource inside the src directory of your Plugin.
The apiVersion should match what the documentation page of the resource type indicates. You can find full documentation on the Solution Execution file here.
Test your changes
At this point, you should build, (solution build), submit (xmt submit extension), and validate (solution validate), to make sure your XM Solution is working. If it does not work right away, pay attention to any errors that the build or validation commands showed you.
You should build, submit, validate, and test frequently! In fact, you can add alias below to your local file to run these three commands together.
For Unix systems, you can add the following line to your shell's rc or profile file.
alias bsv="solution build; xmt submit extension; solution validate"
Then use the source command to load your new config. For example:
source ~/.zshrc
For Windows systems, you can create a .bat file that runs the three commands. You can also add this file to your system PATH, so you can run it from any directory.
Some resources may not work immediately after importing them. You will need to replace some fields specific to your user with something more generic first. Check out the documentation page for the resource you are working with to see if this is the case.
If you are building a simple template, then you are done! Otherwise, keep going to learn how XM Solutions can be customized for users.
Step 4: Collect User input
In order to customize an XM Solution for its users, you have to know something about the user or collect some information from them. The Solution Context is used to store information generated from the steps in your XM Solution execution file or collected from users.
You may want to use this information to customize a resource. Information like the user's preferred language or user ID are always available on the Solution Context. The next step will talk more about how to use the Solution Context.
User information
Some basic user information is always available on the Solution Context.
"system": {
"language": "EN",
"user": {
"userId": "",
"brandId": "",
"dc": ""
}
}
Setup Assistant
Besides the information automatically available, it may be important to collect input from the user. The way to collect user input is by building a Setup Assistant. A Setup Assistant is a form that will allow you to ask the user questions and store their answers on the Solution Context.
To build a Setup Assistant, run solution editor --setupAssistant. This will launch a window in your browser with the editor UI to help you build it. The starter templates for XM Solutions come with a Setup Assistant, so you can upload that file in the UI if you want to use it as a starting point.
After you've built it, you need to add the setup configuration to your Solution Execution file so that the user will see it. If you started from a template, it will come pre-configured. It will look something like this:
{
"setup": {
"formFilePath": "path/to/your/file"
}
}
The Setup Assistant is always the first step of a Solution. You will always need to at least collect the title of the project from the user.
For more information about the context, as well as examples of the various ids generated by resources and setup assistant questions, check out this page.
To learn more about the Setup Assistant resource check out this page
Step 5: Modify resources based on user input
Now that you've collected some input from the user, it's time to use that information to customize the XM Solution for them. This is done by writing JavaScript or Typescript to transform your resource files.
You may have previously noticed the transformationFilePath field in your Solution Execution file. This field is the path to the JavaScript or Typescript file that you would like to use to modify the resource before it gets created. Put the path to your script there, and then write your script. It may look something like this:
// The function to be exported always takes in the resource and the *Solution* context in that order.
function transform(resource: Resource, context: Context) {
resource.brandId = context.user.brandI;
resource.contextId = context.survey.id;
resource.payload.Name = context.setup.answers.title;
resource.userId = context.user.userId;
// A valid JSON object must always be returned.
return resource;
}
// Transformation files always need to export a single function
export default transform;
This is where the Solution Context comes back into play. All of the user input you collected is stored on the context parameter passed into your transform function. You can see that the example above uses context.setup.answers.title to reference the project title that the Setup Assistant asked for.
Importantly, the Solution Context also gives you access to some things you didn't explicitly try to collect. User information and information from previously created resources are also available there. This is crucial for resources that you want to link together at creation time.
In the example above, the Typescript references a survey that was created in a creation step in the Solution Execution file by referencing context.survey.id. This is common for doing things like linking a survey to the dashboard that will display the data collected.
Be sure to check out the documentation for the resources you are using to see what they make available on the context when they are created and if you are using a resource that requires an ID from another one.
You can also see in the example above that the user information is made available on the context automatically. The example used context.user.userId to get the ID of the user that will create an instance of this XM Solution.
Step 6: Set up robust validation and unit testing
At this point, you should have a fully working XM Solution. Congratulations! Now it is time to build some automated tests to make sure it works as expected. It is a best practice to unit test all of your JavaScript/Typescript transformations.
Improving validation
The solution validate command works by running validation against all the "tests" you have in the tests directory in your Plugin. Each of these tests is a JSON representation of the user input you expect to collect for your XM Solution.
To get started with a new validation test, first run solution generate-test. It will output a file that looks something like this:
{
"setup": {
"answers": {
"title": ""
}
},
"system": {
"language": "EN",
"user": {
"userId": "",
"brandId": "",
"dc": ""
}
}
}
This generated file will have all of the fields you are expecting to collect from the user. Fill it out with credible values so the validation can run against a set of inputs you expect.
If different user inputs drastically change how resources are built, then you should make multiple test files. All critical paths of your XM Solution should be tested.
The Solution Execution file supports branching where you might choose to build different resources based on user input. To pass validation, you must test all branches of your Solution Execution file. You will not be able to publish your plugin unless every branch is tested.
Writing unit tests
It is a proven practice to test your JavaScript/Typescript. All of the Plugin templates come set up to use jest to test your code. However, you are welcome to use any testing tools you want as there are many options available.
To get started with jest, check out their documentation here, and be sure to look at the example test files that come in all of the Plugin templates.