# Embed tracks

## Overview

Instruqt allows you to embed tracks into your existing sites or share "Kiosk-mode" links to users, with pre-authorized tokens attached. This guide will cover both approaches, and how to customize each.

{% hint style="info" %}
Only team owners and track authors can customize and obtain these sharing methods.
{% endhint %}

{% hint style="warning" %}
Embeds and kiosk mode links grant learners unlimited access to your track without any form of authentication. We recommend setting [track limits](https://github.com/instruqt/gitbook/blob/master/tracks/share/broken-reference/README.md) as a safeguard.
{% endhint %}

### HTML iframe

You can generate the `<iframe>` code snippet for a track using the Instruqt Web UI.

{% tabs %}
{% tab title="🌐 Web UI" %}

1. Click the track you want to embed in your site.
2. In the header, under the **Share** dropdown, click **Simple** **Embed**.
3. [You can optionally customize](#customization-options) the embed settings under *Customize*. As you select options, the `iframe` code snippet will update.
4. Under the Embed iframe snippet, select **Copy embed code**. The snippet will look similar to the following:\\

   ```markup
   <iframe width="1140"
     height="640"
     sandbox="allow-forms allow-modals allow-popups allow-same-origin allow-scripts allow-popups-to-escape-sandbox"
     src="https://play.instruqt.com/embed/instruqt-demos/tracks/example-track?token=em_Q6XaYOhXp3VSVe6K" style="border: 0;"
     allowfullscreen>
   </iframe>
   ```
5. Copy and paste the `iframe` snippet into your site.
   {% endtab %}
   {% endtabs %}

{% hint style="info" %}
Have an LMS? [We provide an LTI integration that is preferred over simple embeds.](https://docs.instruqt.com/settings/integrations/integrate-with-lti)
{% endhint %}

### Kiosk Mode

Kiosk Mode is a direct link to a full-screen version of the embed experience. You can share the Kiosk mode link with your learners directly or integrate it on your website.

{% tabs %}
{% tab title="🌐 Web UI" %}

1. Click the track you wish to generate a Kiosk Mode link for.
2. In the header, under the **Share** dropdown, click **Simple** **Embed**.
3. [You can optionally customize](#customization-options) the Kiosk Mode URL under *Customize*. As you select options, the URL will update.
4. Click **Copy link** and share with your leaners.
   {% endtab %}
   {% endtabs %}

## **Customization options**

The `iframe` and Kiosk Mode links offer following customization parameters:

| Option                                       | Description                                                                                                                      |
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Show challenges on splash screen             | Provide learners with a preview list of all challenges in the track                                                              |
| Add custom button to finish screen           | *To provide a "Call to action" to learners after they complete your track, by adding a custom button taking learners to a link.* |
| Customize text on finish screen              | Change the default "Great job!" at the end of a track to a custom string.                                                        |
| Disable feedback collection on finish screen | Disable feedback collection if unwanted.                                                                                         |

{% hint style="warning" %}
If you have embedded or linked to a track and later customize the settings, you will also need to update your embed snippet or Kiosk mode link.
{% endhint %}

### **Default URL parameters**

All customization options can also be set programmatically by including the customization parameters in the embed or Kiosk mode url:

* `showChallenges=true` (default = false)
* `finish_btn_text=[YOUR_BUTTON_TEXT]`
* `finish_btn_url=[YOUR_BUTTON_URL]`
* `finish_btn_target= _blank` , `_top` or `_self`
* `finish_text=[YOUR_TEXT]`
* `disable_feedback=true` (default = false)

### Custom URL parameters

Custom parameters are similar to [UTM parameters](https://en.wikipedia.org/wiki/UTM_parameters) in analytics tools. And they give extra contextual information about the current play. For example, the origin of this specific track play.

You pass custom parameters at the end of the URL for embedded tracks. Any parameters prefixed with `icp_` will be stored with the learner's track play and propagated to [webhook events](https://docs.instruqt.com/settings/platform/webhooks) related to that track play. The custom parameters are also reported for each play in the Plays report.

The following example sets the custom parameter called `user_id` to the value `bob123`:

```
https://play.instruqt.com/embed/TEAM/tracks/EXAMPLE?token=TOKEN&icp_user_id=bob123
```

Multiple parameters can be specified by separating them with an `&` symbol:

```
https://play.instruqt.com/embed/TEAM/tracks/EXAMPLE?token=TOKEN&icp_user_id=bob123&icp_campaign=campaignA
```

## Embed event callbacks

Instruqt sends the following events to the parent web page when embedding a track. Instruqt uses the [Window.postMessage()](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) API to send these events.

| Event Name                  | Description                                               |
| --------------------------- | --------------------------------------------------------- |
| `track.started`             | A learner starts a track (clicks "Launch")                |
| `track.ready`               | The track's sandbox is ready to start (loading completed) |
| `track.challenge_started`   | A learner starts a challenge                              |
| `track.challenge_skipped`   | A learner skipped a challenge                             |
| `track.challenge_completed` | A learner or the platform stopped a track                 |
| `track.completed`           | A learner completes a track                               |

{% hint style="info" %}
You can use these events to store a learner's progress or trigger other events or behaviors in your systems.
{% endhint %}

## One-time play token

You can replace any of the tokens referenced above with a one-time play token. These tokens can be generated using our GraphQL API and are valid for a single play only. A one-time token is automatically invalidated after use, or after 24 hours if unused.

You can optionally include user details when generating the token. When the token is claimed for a play, the associated details will be set for the user who claimed it.

{% tabs %}
{% tab title="Terminal" %}
Open a terminal and run the following `curl` command:

```bash
cat >query.json <<EOF
{
  "query": "mutation {
    generateOneTimePlayToken(
      trackID: \"TRACK_ID\",
      userDetails: {
        firstName: \"Jane\",
        lastName: \"Smith\",
        email: \"jane.smith@example.com\"
      }
    )
  }"
}
EOF

curl -H "Authorization: Bearer YOUR_API_KEY" -X POST -d @query.json https://play.instruqt.com/graphql
```

{% endtab %}
{% endtabs %}

## Capture user details via a custom web integration  (previously called third party forms)

Users can play an embedded track without logging in or creating an account. While convenient, this results in reporting metrics and events being anonymous.

If you're gating access with your own form or already have user information, you can securely share this data with the embedded track to enhance reporting and add more value to [Integrations](https://docs.instruqt.com/settings/integrations). To achieve this, leverage the personally identifiable information (PII) parameter to seamlessly link user details by following these steps:

### Step 1

Copy and paste the following code snippets in the same place where the track is being embedded:

<details>

<summary>Encryption function</summary>

```javascript
async function encryptPII(publicKeyPEM, fields) {
  const encodedPII = new TextEncoder().encode(
    new URLSearchParams(
      [
        ['fn', fields.firstName],
        ['ln', fields.lastName],
        ['e', fields.email],
      ].filter(([, value]) => value)
    ).toString()
  );

  const publicKeyDER = Uint8Array.from(
    atob(publicKeyPEM.replace(/-----[^-]+-----|\s/g, '')),
    (char) => char.charCodeAt(0)
  );

  const publicKey = await crypto.subtle.importKey(
    'spki',
    publicKeyDER,
    { name: 'RSA-OAEP', hash: 'SHA-256' },
    false,
    ['encrypt']
  );

  const encryptedPII = await crypto.subtle.encrypt(
    { name: 'RSA-OAEP' },
    publicKey,
    encodedPII
  );

  return btoa(
    String.fromCharCode.apply(
      null,
      Array.from(new Uint8Array(encryptedPII))
    )
  );
}
```

</details>

<details>

<summary>Usage example</summary>

```javascript
const trackLink = '…'; // Invite or embed url
const encryptionKey = '…'; // The public key

const encryptedPII = await encryptPII(encryptionKey, {
  firstName: 'John',
  lastName: 'Doe',
  email: 'john.doe@acme.com',
});

const trackLinkWithPII = new URL(trackLink);
trackLinkWithPII.searchParams.set('pii_tpg', encryptedPII);

// Link with user details encrypted into it:
trackLinkWithPII.toString();
```

</details>

### Step 2

Customize the usage example code snippet you just pasted:

1. Fill the `trackLink` variable with the same URL from the embed
2. Fill the `encryptionKey` variable with the encryption key of your team\
   Get it at **API keys** in **Settings**, under the **PII Encryption** section
3. Replace `firstName`, `lastName` and `email` with the information that you have on the user

### Step 3

Change your embed to use the new link generated in the usage example code snippet.

Notice how the new link now has a, rather long, parameter called `pii_tpg` in it, that's how the information about the user is securely shared with the embedded track. Only Instruqt can decrypt it.

### Step 4

All set! Any activity in the track will now be associated with the user details you provided with the `pii_tpg` parameter.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.instruqt.com/tracks/share/embed-a-track.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
