Embed a capsule on your site
Any published capsule can live on your own pages: a blog post, a newsroom, a product launch. It's a standard iframe, so it works in any CMS that accepts HTML. No script, no account and no key.
Quick start
In the editor, choose Published at the top, then Copy embed code. Or write it yourself from the capsule's link:
<iframe
src="https://app.capsules.ink/your-space/your-capsule"
title="The night shift, a capsule"
width="100%"
height="640"
style="border: 0"
allow="autoplay; fullscreen; clipboard-write"
allowfullscreen
loading="lazy"
></iframe>titlenames the frame for screen readers. Use the capsule's title.allowlets sound play after the reader taps, the reader go full screen, and links and quotes be copied.loading="lazy"waits to load the capsule until the reader scrolls near it.
In WordPress, Ghost, Webflow, Squarespace and most other platforms, paste it into an HTML or embed block.
Here it is at work. Scroll inside the frame, and watch the progress it reports to this page:
Sizing
A capsule scrolls inside its own frame and lays itself out for the frame, not the browser window. Any size works. Two common choices:
Inline
Full width and 640 pixels tall, as in the quick start. It sits in the flow of an article like a video, and the reader scrolls through the story inside it.
Full screen
Make the frame as tall as the screen, so the capsule fills the view while it's being read. Pair it with the scroll hand-off so readers can carry on down your page afterwards.
<iframe
id="capsule"
src="https://app.capsules.ink/your-space/your-capsule"
title="The night shift, a capsule"
style="display: block; width: 100%; height: 100vh; height: 100svh; border: 0"
allow="autoplay; fullscreen; clipboard-write"
allowfullscreen
loading="lazy"
></iframe>100svh keeps the frame clear of the browser's toolbars on phones; 100vh is the fallback for older browsers.
Phones
Frames 768 pixels wide or narrower get the mobile layout, wherever they appear. A narrow column on a desktop page shows the mobile layout too. Give the frame the full width of the screen on phones.
Scroll hand-off
While the pointer is over the frame, scrolling moves the capsule, not your page. Browsers don't let a page read scroll position inside a frame from another site, so the capsule reports it instead with postMessage. This listener lets your page take over once the reader reaches the end:
<script>
const CAPSULE_ORIGIN = "https://app.capsules.ink"
const frame = document.getElementById("capsule")
window.addEventListener("message", (event) => {
// Only trust messages from the capsule you embedded.
if (event.origin !== CAPSULE_ORIGIN || event.source !== frame.contentWindow) return
const message = event.data
if (!message || message.type !== "capsules:progress") return
// At the end, let the wheel and touch fall through to the page.
if (message.atEnd) frame.style.pointerEvents = "none"
})
// Hand control back to the capsule once it has left the screen,
// so a reader scrolling back up can read it again.
new IntersectionObserver(([entry]) => {
if (!entry.isIntersecting) frame.style.pointerEvents = "auto"
}).observe(frame)
</script>Always check event.origin. A capsule posts its messages to whichever page embeds it, so any frame could send a message that looks like one.
Drive the capsule from your page
To tie the capsule to your own scrolling, for example a pinned section that plays the story as the page scrolls past, send it a position:
frame.contentWindow.postMessage(
{ type: "capsules:scrollTo", percent: 0.5 },
"https://app.capsules.ink",
)Messages
Every message is an object with a type. These are the ones meant for your page. Ignore any other type you see: they belong to the Capsules editor and can change.
From the capsule
| type | Fields | Meaning |
|---|---|---|
capsules:ready | None | The capsule has loaded and is listening for messages. |
capsules:first-frame | None | The first frame is on screen. |
capsules:progress | percent, atEnd | The reader scrolled. percent runs from 0 to 1; atEnd is true at the bottom. Sent at most once per frame, and once on load. |
capsules:edition | edition, label, source | The edition changed, by the reader (source: "reader") or by you ("host"). |
To the capsule
| type | Fields | Meaning |
|---|---|---|
capsules:scrollTo | percent | Scroll the capsule to a point from 0 to 1. Ignored while the title screen shows. |
capsules:set-edition | edition | Switch to the edition with this slug. |
Send messages to the capsule with its origin, https://app.capsules.ink, as the target. Wait for capsules:ready before sending, or the capsule may not hear you.
Starting points and editions
- Add
#sand a scene number to the link to open at that scene. Scenes count from 0, so#s2opens the third. - A capsule with editions opens the edition named in
?edition=, for example?edition=night. Readers can still switch, and you hear about it incapsules:edition.
Host page requirements
Capsules can be framed by any site. You don't need to register your domain. If your page sends a Content Security Policy, allow the capsule's origin:
Content-Security-Policy: frame-src https://app.capsules.ink; child-src https://app.capsules.inkAvoid sandbox on the frame. If your platform requires it, these permissions keep the capsule working: scripts and its own storage to play, forms for the subscribe form, popups for sharing, and top navigation for the link to the next capsule.
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"oEmbed
Capsules support oEmbed, so platforms that use it can embed a capsule from its link alone. Each capsule page advertises the endpoint, and you can call it yourself:
curl "https://app.capsules.ink/api/oembed?url=https%3A%2F%2Fapp.capsules.ink%2Fyour-space%2Fyour-capsule&maxwidth=640"{
"version": "1.0",
"type": "video",
"title": "The night shift",
"provider_name": "Capsules",
"width": 640,
"height": 360,
"html": "<iframe src=\"https://app.capsules.ink/your-space/your-capsule\" width=\"640\" height=\"360\" …></iframe>",
"thumbnail_url": "https://…"
}urlis the capsule's published link. Onlyformat=jsonis supported.maxwidthandmaxheightare optional. The default is 720 by 405.typeisvideowhen the capsule has a short preview clip, andrichotherwise. Both embed the capsule itself.- White-label capsules don't advertise the endpoint and leave out Capsules as the provider.
Performance
- The cover image is part of the capsule's page, so the frame shows a picture straight away.
- The first scene's video loads first. Later scenes load as they're needed, at a quality that suits the reader's device and connection.
- Most of a capsule's weight is video, so use
loading="lazy"for any capsule below the fold, and avoid several full-screen capsules on one page.
Search and fallbacks
Search engines credit a capsule's words to its own link, not to your page. Give your page its own title, description and a few lines of introduction, and add a plain link to the capsule after the frame for readers whose browsers block frames:
<iframe src="https://app.capsules.ink/your-space/your-capsule" …></iframe>
<p><a href="https://app.capsules.ink/your-space/your-capsule">Read “The night shift” on Capsules</a></p>Analytics
Reads of an embedded capsule count towards its views in Capsules, the same as reads on its own link. Capsules doesn't break views down by site. To measure reading on your page, forward progress to your own analytics:
const seen = new Set()
window.addEventListener("message", (event) => {
if (event.origin !== "https://app.capsules.ink") return
const message = event.data
if (!message || message.type !== "capsules:progress") return
for (const mark of [0.25, 0.5, 0.75, 1]) {
if (message.percent >= mark && !seen.has(mark)) {
seen.add(mark)
// Replace with your analytics call.
track("capsule_progress", { percent: mark * 100 })
}
}
})Updates and caching
- Republishing keeps the link, so every embed shows the new version within a minute or two. You don't change the embed code.
- Renaming the link when you republish breaks embeds that use the old one. It isn't redirected.
- Unpublishing makes every embed of the capsule show a not-found page within a minute or two.
- Improvements to the Capsules reader reach a capsule the next time it's published, so republish older capsules to pick them up.
Inside the frame
- Sound only starts after the reader taps or clicks in the capsule, as browsers require.
- The link to the next capsule in a series opens in your page's tab. Share, subscribe and profile links open a new tab.
- The subscribe form works inside the frame and adds readers to the capsule creator's list.
- Every published capsule can be embedded. There are no supporter-only capsules yet.