Your page in an activity

Put your own web page inside a course activity, record what learners do in it, and let the AI beside it know.

2 min read · Updated Oct 29, 2026

Put your own page, such as a fractions game or a lab simulation, inside a course activity. An agent can sit beside it, and what learners do there goes into the research export.

Courses are set up in the dashboard or with the CLI, not with API keys. Your page never learns who the learner is; VIABLE records its events with the learner.

Set up the activity

  1. Serve your page over https. Let https://page.viablelearning.org frame it, for example with Content-Security-Policy: frame-ancestors https://page.viablelearning.org.
  2. Add the panel. In Teach → Courses, open the course, add an activity, and add an Embedded page panel with your page's address.
  3. Choose what the agent is shown. If the activity has an agent, pick Its events, Nothing or Custom.
  4. Say how it ends. Turn on It says when the learner is done if your page reports completion. Otherwise learners press "I'm done".

Serve the page from exactly that address: a redirect to another origin cuts the connection. The frame is sandboxed (allow-scripts allow-same-origin allow-forms allow-popups allow-pointer-lock) and gets no referrer.

Add the bridge

Any page works as it is. To record what happens and tell the agent, add a few postMessage calls. The panel's Connect your page (optional) offers them to copy:

js
let session = null
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://page.viablelearning.org') return
  if (e.data?.viable === 1 && e.data.type === 'hello') session = e.data.session
})
const viable = (message) => window.parent.postMessage({ viable: 1, ...message }, 'https://page.viablelearning.org')

viable({ type: 'hello' }) // asks for hello again, if you started listening late
viable({ type: 'event', verb: 'answered', object: 'level-2', success: true, score: 1, max_score: 1 })
viable({ type: 'state', data: { level: 2, pieces: 3 } })
viable({ type: 'ask', text: 'Can I get a hint?' })

session is a random ID for this visit. Ignore other origins.

type What happens
event Kept as an event: a verb and optionally object, score, max_score, success, completion, response, duration_ms and data.
state What your page shows now, kept at most every 5 seconds.
ask Puts text in the chat box for the learner to send. Nothing is sent for them.
hello Asks for the hello again if your page started listening late.

Prefer xAPI verbs: attempted, answered, completed, passed, failed, progressed, interacted. data holds up to 20 fields of numbers, true/false values or strings up to 200 characters. With It says when the learner is done, the first completed event, or one with completion: true, counts toward the activity being done.

What the AI sees

With Its events, when a learner asks while your panel is open, the step writing the reply sees your page's last ten events and its latest state. Custom sets 0–20 events and whether the state is included. The agent's Profile sets where this enters the prompt, and any step can read it as {{context.workspace}}. Learners are told on the panel what the agent sees.

What gets recorded

Events and states are kept with the learner, course, activity and activity version, at every recording level. The research export has them in workspace_events.csv. When a study runs in the course, its consent and conditions apply as in any activity.

  • Activities: build the activity around your page.
  • Export: download the events with the course's data.

This page is also plain Markdown at /docs/connect/embed.md. Point your AI at /llms.txt to find every page.