Embed an activity anywhere
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:
<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. 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.
<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>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:
<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.
<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,
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:
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.
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 |