Documentation

How UX Signals works

After you or your researcher have created a study you will be presented with a simple code snippet consisting of a HTML DIV-tag and a script. At this point you or your developer need to place this code somewhere on your page. The simplest way to do it is to just copy and paste the code snippet wherever you want it to be displayed, but in some cases you'll have to integrate it a bit deeper into your code, depending on how your page is built.

NB! It is important to note that the script only runs once after the page is loaded, and does not check for updates. If you have a single page application or want to conditionally render the embed, you'll have to add the script after you are certain the div is rendered on the page. You can read more about this and see some examples here.

Embed on a website

Example of what a rendered widget may look like
Example of what a rendered widget may look like

The code snippet

When you create a new project you get a code snippet like the example below. This can be pasted in anywhere on your webpage, and will render out where you put it.

<div data-uxsignals-embed="panel-xopvvxqfwp" style="max-width: 620px" data-uxsignals-env="localhost"></div> <script src="http://localhost:8080/embed.js"></script> // Need more help? See: https://app.uxsignals.com/docs
Embed code example.

The code snippet consists of a script and a div with an id as a property. For testing and in your test environment we recommend you add the demo-property as you see in the table below. You can also add some simple styling and set the primary color. See more about styling here.

PropertyDescriptionExample value
data-uxsignals-embedThe id.panel-xopvvxqfwp
data-uxsignals-modeOptional. Allows for testing without bookings going through. Read more about demo mode here. demo
styleOptional. Read more about styling and class names here.{{ maxWidth: '620px' }}

Demo mode for your test environment

The property data-uxsignals-mode should be used when you're testing. This make sure that you can play around with the widget without any data being stored.

Web

data-uxsignals-mode={env === 'test' ? 'demo' : ''}

Mobile

https://api.uxsignals.com/v2/study/id/panel-xopvvxqfwp/active?mode=demo

In demo mode, widget will always be active.

Single page applications

For single page applications (React, Vue, Angular, etc) simply pasting the snippet where you want it may not work due to the way they update the page content. For React applications you can then omit the script tag from the embed code, and instead add the code using a React hook. The example hook below takes in a boolean which can be used to avoid loading the script before the page is done fetching data, or other conditions for rendering the embed.

import { useEffect } from 'react';

const useScript = (ready: boolean) => {
    useEffect(() => {
        const script = document.createElement('script');
        script.async = true;
        script.src = "https://widget.uxsignals.com/embed.js";
        if (ready) {
            document.body.appendChild(script);
        }

        return () => {
            try {
                document.body.removeChild(script);
            } catch {}
        };
    }, [ready]);
};

export default useScript;
Example of React hook to load the script. The ready parameter can be used to avoid adding the script before the page is done loading.
import useScript from 'hooks/useScript';

const MyComponent = () => {
    useScript(true); 

    return (<div
                data-uxsignals-embed="panel-xopvvxqfwp"
                style={{ maxWidth: '620px' }}
            />);
}
Example of how to use the hook above.

Styling of embedded widget

If you want to adjust the padding or size of the widget, you can use uxsignals-container. For everything elses cope it within uxsignals-embed for example

.uxsignals-embed .uxsignals-cta { ... }
This will change the styling of the cta's.

Below you will see the 5 classes we support

ClassnameDescription
uxsignals-containerThis is the container placed directly inside the div from the code snippet
uxsignals-embedThis is the container that surrounds the embedded widget.
uxsignals-headerThe header. Use within uxsignals-embed.
uxsignals-descriptionAn arbitrary long text with line breaks and emojis. Use within uxsignals-embed
uxsignals-ctaThis is the call-to-action button that will open the modal for bookings. Use within uxsignals-embed

CSP

If your site has CSP headers, you need add these for UX Signals:

CSP propertyValue
script-src https://widget.uxsignals.com
connect-srchttps://api.uxsignals.com
style-srcunsafe-inline
img-srchttps://widget.uxsignals.com

Events

We have an event that is triggered when someone books a meeting or joins a pre-recruiting list. For instance, you can use this event to hide the widget for them. In the browser this works out of the box, as we communicate via window.postMessage. If you implement it on iOS or Android, you need to set up a namespace called uxsignals via WKUserContentController on iOS, and via addJavascriptInterface on Android. The callback method we expect in the namespace is postMessage. We have one event:

  • bookingCompleted: When a booking is completed
The stringified object you receive looks like this:

{
  "command": "'bookingCompleted'"
}

You could also share the project via a link. This will work the same as if you embed the widget.

https://app.uxsignals.com/dialog/panel-xopvvxqfwp

Mobile app

There are two ways to do this: one is by having a single CTA (Call to Action) that opens the link (https://app.uxsignals.com/dialog/panel-xopvvxqfwp) in a WebView / Browser (remember to use the /active endpoint to verify that the study is active) Alternatively, you can use the/active to retrieve the first question from the study and employ a small widget that displays this question. When the user clicks on any question, use the answerUrl that question to open the webview.

API

Active endpoint

The active endpoint is important if you're constructing your own widget or utilizing the shared link, it's essential to use this endpoint to confirm the study's activity status and/or retrieve the initial question to build your widget.

https://api.uxsignals.com/v2/study/id/panel-xopvvxqfwp/active
Response example
{
  "active": true,
  "language": "no",
  "widgetUrl": "https://app.uxsignals.com/dialog/panel-xopvvxqfwp",
  "firstQuestion": {
    "header": "The header for the first question",
    "description": "Here is a optional description that you should show if it exists.",
    "options": [
      {
        "label": "Label for answer option #1",
        "position": 0,
        "answerUrl": "https://app.uxsignals.com/dialog/panel-xopvvxqfwp?answer=0"
      },
      {
        "label": "Label for answer option #1",
        "position": 1,
        "answerUrl": "https://app.uxsignals.com/dialog/panel-xopvvxqfwp?answer=1"
      }
    ]
  }
}

Note: If the QuestionType is checkboxes, the user can select multiple options. In such cases, you need to construct the URL yourself by appending each selected option's position to the widget URL. For example:

https://app.uxsignals.com/dialog/panel-xopvvxqfwp?answer=0&answer=1

Typescript types
Typescript types: 
type ActiveEndpointRes = {
    active: boolean;
    language: 'en' | 'no' | 'fi' | 'da';
    widgetUrl: string;
    questionType:
        | 'calendarStep'
        | 'checkboxes'
        | 'multipleChoice'
        | 'studyPanel';
    header: string;
    description: string;
    options: Array<{
        label: string;
        position: number;
        answerUrl: string;
    }>
};

Debug mode / demo mode

During development you should append ?mode=demo to the url to get the mode of the service

https://api.uxsignals.com/v2/study/id/panel-xopvvxqfwp/active?mode=demoWhen the demo mode is active we don't store any data, active is always true and we always pre-populate with slots you can book