---
title: "Run a Zentrik study inside a web prototype"
canonical_url: https://zentrik.ai/docs/developers/prototype-studies-sdk
markdown_url: https://zentrik.ai/docs/developers/prototype-studies-sdk.md
category: "Developer docs"
learning_track: null
last_reviewed: 2026-08-10
---

# Run a Zentrik study inside a web prototype

Add one script to a prototype, guide participants through configured steps, and review timestamped widget and prototype interactions without putting participant identity in the prototype URL.

## Overview

Prototype studies begin with a blocking Zentrik dialog over a web prototype, followed by a movable task guide. The prototype remains responsible for its own screens and behavior; Zentrik supplies the participant identity or anonymity choice, welcome and final messages, ordered steps, session continuity, and interaction timeline.

Use this method when participants need to complete tasks in an interactive prototype and you want to see when they used the study widget, moved to a meaningful part of the prototype, or clicked a control you marked for the study. For other study methods and the product research workflow, read [Studies](https://zentrik.ai/docs/product/idea-studies).

## How prototype studies work

A prototype study has two parts:

- **Zentrik configuration** defines the study name, target prototype URL, widget theme, inactivity timeout, participant-facing welcome and final messages, ordered steps, and event-driven contextual steps.
- **Prototype integration** loads the generated script and optionally launches contextual steps or identifies meaningful navigation and clicks.

When the study is active, the script loads its saved configuration and opens a centered dialog that blocks the prototype. The participant identifies themselves or explicitly continues anonymously before the task guide begins, then works through the steps and chooses the configured completion, comment, or skip actions. Zentrik records those actions in one participant session and shows the session under **Responses**.

The widget runs in an isolated shadow root so the prototype's page styles do not restyle it. Participants can collapse or move the widget when it covers the part of the prototype they need.

## Set up the prototype

1. Open the Study and select **Prototype**.
2. Enter the target prototype URL and choose the light or dark widget theme.
3. Edit the welcome message, steps, optional step media, action labels, optional comment and skip actions, and final message. Upload a PNG, JPEG, GIF, or WebP image up to 15 MB, or an MP4 or WebM video up to 100 MB. Add a concise description so the media has an accessible label.
4. Set the inactivity timeout. It accepts 30–86,400 seconds, defaults to 600 seconds, and ends a session when no click, key press, touch, scroll, media playback, or navigation occurs during that window.
5. Mark any event-driven guidance as a **Contextual step**. Copy the step ID shown in its options and connect it to the matching prototype event with **launchStep(stepId)**.
6. Copy the generated **Script tag** into the prototype's HTML.
7. Activate the prototype study and reload the prototype.

Use the generated tag exactly as shown in Zentrik. It includes the correct script host and the unique study key:

~~~html
<script
  async
  src="https://your-zentrik-host.example/api/public/study-script/v1.js"
  data-zentrik-key="zk_your_study_key"
></script>
~~~

The script sends study events back to the same Zentrik origin that served it. If the prototype uses a Content Security Policy, allow that origin in both **script-src** and **connect-src**. Uploaded media uses short-lived private playback links; allow the media delivery host shown by the browser in **img-src** and **media-src**.

## Participant identity and sessions

Participants either enter their name, email, and company in the blocking start dialog or choose **Continue anonymously**. Zentrik remembers a submitted identity in the browser so a returning identified participant does not need to enter it for every study visit. Anonymous sessions do not create a participant identity. Participant identity is never added to the prototype URL.

An unfinished session is also remembered in the browser. Reloading the prototype or reopening it in the same browser resumes the server-validated session instead of creating another response. Completing or declining the study closes that session. A later visit can then create a new session while reusing the remembered identity.

The configured inactivity timeout also closes an unfinished session as **Abandoned** when the participant takes no action for that many seconds. Activity restarts the timer, and the timeout saved when the session begins remains attached to that response even if an editor later changes the study setting.

A different browser, cleared browser storage, or private-browsing boundary starts a separate session because the previous session credentials are no longer available.

## What Zentrik captures

The session detail in **Responses** includes:

- participant identity, when supplied, and session status
- session start and total duration
- timestamped interactions with elapsed time from session start
- widget actions such as identifying, continuing anonymously, starting, collapsing, expanding, completing a step, commenting, skipping, declining, and closing
- semantic navigation levels sent through the SDK
- clicks on elements marked with the study click attribute
- the active step associated with each captured interaction

Ordinary prototype clicks contribute to step interaction counts, but Zentrik does not infer their meaning. Use a tagged click when a specific prototype control should appear by name in the session timeline.

## SDK reference

After the participant session starts, the script exposes **window.zentrikStudy**. The compatibility alias **window.__zentrikStudy** remains available, but new prototype code should use the public name.

~~~javascript
window.zentrikStudy.version;            // "1"
window.zentrikStudy.navigate(level);    // record a semantic destination
window.zentrikStudy.track(name);        // record a custom milestone in the active step
window.zentrikStudy.launchStep(stepId); // display a contextual step by ID
~~~

The script loads asynchronously. Call the SDK from participant interactions that happen after the widget has loaded, and guard calls with optional chaining when the prototype can also run without the study script:

~~~javascript
window.zentrikStudy?.track('booking-editor-opened');
~~~

**track(name)** records a short custom milestone on the active study step. If no step is active, the call does nothing. Use **navigate(level)** for destinations, **launchStep(stepId)** for authored contextual guidance, and the HTML data attribute for meaningful element clicks.

## Launch contextual steps

Contextual steps appear only when prototype code launches them. In the study editor, create or select a step, enable **Contextual step**, and copy the stable **Step ID** shown in the step options. A contextual step is excluded from the ordinary numbered sequence.

Call **launchStep(stepId)** from the prototype event that should display the guidance:

~~~javascript
function openUpgradeDialog() {
  renderUpgradeDialog();
  window.zentrikStudy?.launchStep('upgrade-help-step-id');
}
~~~

The call returns **true** when the matching contextual step opens and **false** when it cannot open. The participant must have started an ordinary step, the ID must belong to a contextual step in the active study, and another contextual step cannot already be open.

The contextual step temporarily replaces the active ordinary step in the widget. After the participant completes, skips, or comments on it, the widget returns to the ordinary step they were completing. Contextual steps can be launched more than once during a session, and each completed appearance is recorded as its own task run.

Step IDs are authored identifiers, not labels. Copy the ID from Zentrik instead of deriving it from a step title, and update prototype code if the contextual step is deleted and recreated.

## Record navigation

Call **navigate(level)** after the prototype moves to a meaningful screen, layer, or workflow level. Send a stable product label rather than a full URL.

~~~javascript
function showRoute(route) {
  history.pushState({}, '', route.path);
  render(route);
  window.zentrikStudy?.navigate(route.level);
}

showRoute({ path: '/appointments', level: 'appointments' });
~~~

The session timeline records **Navigated to appointments** at the time of the call. Repeated calls are kept as separate interactions because returning to a level can be meaningful during a task.

## Record tagged clicks

Add **data-zentrik-study-click** to any HTML element whose click matters to the study. The attribute value becomes the stable label in the response timeline.

~~~html
<button data-zentrik-study-click="reschedule-booking">
  Reschedule
</button>
~~~

The script uses delegated click observation, so the attribute also works on elements rendered later by a single-page application. A tagged element can be a button, link, or another interactive HTML element. Keep the value short, descriptive, and stable across prototype revisions.

## Privacy and safe labels

The study script does not read input values, page text, clipboard contents, or form state. Automatically observed paths omit query strings and fragments and mask identifier-shaped path segments before they are sent.

Uploaded step media is stored privately by Zentrik and delivered to active-study participants through short-lived playback links. The media delivery provider can receive ordinary web request metadata such as IP address and user agent; participant identifiers are not placed in the media URL.

Values supplied explicitly through **navigate**, **track**, and **data-zentrik-study-click** are recorded as authored. Do not put names, email addresses, account identifiers, tokens, free-form user content, or other sensitive values in those labels. Prefer controlled labels such as **appointments**, **checkout-review**, or **confirm-booking**. Pass only the contextual step ID copied from Zentrik to **launchStep**.

## Test the integration

Use this checklist before inviting participants:

1. Activate the study and open the exact target prototype URL in a browser.
2. Confirm the centered identity dialog blocks interaction with the prototype and uses the configured widget theme.
3. Test both identity submission and **Continue anonymously**, then complete at least one configured step.
4. Trigger every **navigate** call, contextual **launchStep** call, and tagged click you expect the prototype to record. Confirm each contextual step returns to the interrupted ordinary step.
5. Reload during the unfinished study and confirm the widget returns without adding another session.
6. Open **Responses**, select the prototype session, and verify the interaction order, timestamps, duration, step context, and labels.
7. Finish the study and confirm the session status changes to **Completed**.

Test in the same hosting and Content Security Policy environment participants will use. A local prototype can load a local Zentrik script during development; deployed prototypes should use the script tag generated by their deployed Zentrik environment.

## Troubleshooting

### The widget does not appear

Confirm the study is active, the generated key belongs to that study, and the browser can load the script URL. Check the prototype's **script-src** policy when the script request is blocked.

### The widget appears but events do not arrive

Check whether the Zentrik origin is allowed by **connect-src** and whether the public session requests succeed. Keep the generated script host and study key together instead of combining values from different environments.

### Reloading creates another session

Use the same browser and study key, and do not clear site storage between loads. A completed or declined session intentionally does not resume. Private browsing and browser policies that block local storage can also prevent continuity.

### A navigation or click is missing

Call **navigate** after the destination is rendered, and confirm **window.zentrikStudy** exists at interaction time. For tagged clicks, put **data-zentrik-study-click** on the clicked element or one of its ancestors and give it a non-empty value.

### A contextual step does not appear

Confirm the participant has started an ordinary step, the editor marks the target as **Contextual step**, and the exact step ID is passed to **window.zentrikStudy.launchStep**. The call returns **false** for an unknown or ordinary step ID, after the session ends, before an ordinary step starts, or while another contextual step is open.

### Step media does not load

Confirm the upload finished and the study remains active. Check the prototype's **img-src** and **media-src** Content Security Policy directives when the browser blocks the private playback link.

## Related guides

- [Signals API quickstart](https://zentrik.ai/docs/developers/signals-api-quickstart)
- [Signals import template](https://zentrik.ai/docs/developers/signals-import-template)
- [Set up Ideas Portal JWT SSO](https://zentrik.ai/docs/developers/ideas-portal-jwt-sso)
