# Embed an activity anywhere

> Put a LearnHouse activity on any website with an iframe: fit it to its content, set colours and language, and react when learners finish.

Every page, video and PDF activity has an embed link. Paste it into a blog post, a help center article, a Notion
page or a slide, and learners use it right there.

## Get the embed code

### Open the activity

Open the activity as a learner would, in its course.

### Share → Embed

Open the **Share** menu at the top of the activity and choose **Embed**. The embed code is copied to your clipboard.

### Paste it

Paste the code anywhere that accepts HTML. Most site builders have an "HTML" or "Embed" block for this.

The copied code looks like this:

```html
<iframe
  src="https://learn.your-school.com/embed/your-school/course/9f2a…/activity/0b3c…"
  width="100%"
  height="600"
  style="border:0"
  allow="fullscreen; autoplay"
  allowfullscreen
  data-learnhouse-embed
></iframe>
<script src="https://learn.your-school.com/embed.js" async></script>
```

The iframe works on its own. The `embed.js` script is optional: it fits the iframe to its content and lets your page
[listen to what learners do](#events). Add it once per page, however many activities you embed.

## Try the options

Change the values below and copy the result. Embed URLs use the bare ids, so the builder drops the `course_` and
`activity_` prefixes if you paste full ids.

## URL parameters

| Parameter | Example | What it does |
| --- | --- | --- |
| `bgcolor` | `bgcolor=f8fafc` | Page background, as a hex colour without `#`. It is applied before the page paints, so there is no white flash on dark sites. |
| `textcolor` | `textcolor=1e293b` | Text colour for the activity, hex without `#`. |
| `bgcolor` | `bgcolor=transparent` | No background, so the activity sits on your page's own background. |
| `showlearnhouselogo` | `showlearnhouselogo=false` | Hides the small LearnHouse badge in the corner. |
| `locale` | `locale=fr` | Shows buttons, labels and player controls in this language instead of the organization's default. Any language LearnHouse ships works; anything else is ignored. |

> On LearnHouse Cloud's Free plan the badge is always shown. Paid plans can hide it with `showlearnhouselogo=false`,
> and white-label plans never show it. Self-hosted instances follow the org's watermark setting.

## What can be embedded

| Activity | Embeds |
| --- | --- |
| Pages (dynamic activities) | Yes, with every block: quizzes, flipcards, scenarios, code playgrounds, math, images, video, audio, PDFs |
| Markdown and embedded-URL pages | Yes |
| Videos | Yes |
| PDF documents | Yes |
| Assignments, SCORM and other types | No. The embed shows a card linking to the activity instead |

Only **published** activities embed. Visitors see what a signed-out visitor of your site would see, so the course has
to be public for the content to show.

## Sizing

With `embed.js` on the page, the iframe takes the height of its content and keeps following it as images load and
blocks expand. The `height` attribute is only the starting height, used until the activity has loaded.

To keep a fixed height and let the activity scroll inside the frame, leave the script out, or opt one iframe out:

```html
<iframe src="…" height="600" data-learnhouse-embed data-learnhouse-autoresize="false"></iframe>
```

## Events

`embed.js` turns what happens inside the activity into DOM events on the iframe. They bubble, so one listener on
`document` covers every embed on the page. The details are in `event.detail`.

```html
<script>
  document.addEventListener('learnhouse:complete', (event) => {
    markLessonDone(event.detail.activityId)
  })
  document.addEventListener('learnhouse:media', (event) => {
    if (event.detail.action === 'ended') analytics.track('video_finished', { activity: event.detail.activityId })
  })
</script>
```

| Event | `detail` fields | When |
| --- | --- | --- |
| `learnhouse:ready` | | The activity is on screen |
| `learnhouse:resize` | `height`, `width` | Its content size changed |
| `learnhouse:complete` | `reason` (`scrolled_to_end` or `media_ended`) | The learner reached the end of the activity, or a video or audio played to the end. Once per load |
| `learnhouse:media` | `action` (`play`, `pause`, `ended`), `media` (`video`, `audio`), `currentTime`, `duration` | Video and audio playback |
| `learnhouse:link_click` | `external` | A link inside the activity was clicked |
| `learnhouse:unavailable` | | The activity can't be shown: it doesn't exist, isn't published, or its type doesn't embed |

Every `detail` also has `activityId`: the bare id from the embed URL.

Any site can frame an embed, so the events carry no content: no media URLs, no link targets, and one `unavailable`
signal whatever the cause. For the full details, render the activity with the [React component](https://docs.learnhouse.app/developers/react),
whose events include them.

### Without the script

The events come from `postMessage` messages the embed sends to its parent page, so you can also read them yourself:

```js
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://learn.your-school.com') return
  const message = event.data
  if (message?.source !== 'learnhouse' || message.version !== 1) return
  // message.type is ready, resize, complete, media, link_click or unavailable
})
```

Check `event.origin` against your LearnHouse address, since any frame on the page can post messages.

> Completion here means the learner saw the end of the activity on your site. To record progress in LearnHouse
> itself, the learner has to be signed in to LearnHouse, or you record it from your server with the
> [SDK](https://docs.learnhouse.app/developers/sdk/resources).

## Performance

The embed renders the activity without starting the editor, and loads each block's code only when the activity uses
that block. A text-and-quiz lesson loads a fraction of what the full course player does.

## Embed vs. the React component

|  | Embed | `<LearnHouseActivity>` |
| --- | --- | --- |
| Setup | Paste HTML | `npm install` |
| Styling | Background, text colour, language, badge | Full theme, your fonts, block overrides |
| Height | Follows the content with `embed.js` | Follows the content |
| Events | Ready, size, completion, media, links (with `embed.js`) | Load, ready, size, links, media, completion, analytics |
| Works on | Any site | React apps |
