Drop-in
Two ways to put a surface on a page. The loader is less work; the plain iframe gives you full control.
The loader
Section titled “The loader”Add a placeholder element and the script. The script finds every element with data-missless-social, creates the iframe, and keeps its height in sync with the content.
<div data-missless-social data-session="mle_5c1e9a7b3d2f8e4a6c0b9d1f7e3a5c2b" data-surface="composer"></div><script src="https://social.missless.tel/widget.js" async></script>| Attribute | Notes |
|---|---|
data-missless-social |
Marks the element. No value needed |
data-session |
The token from POST /v1/embed-sessions |
data-surface |
composer, calendar, inbox, accounts or all. Default all |
The loader:
- creates an
<iframe>inside the element withwidth: 100%, no border, and the rightsrc; - listens for
resizemessages from the iframe and sets the height, so the page never shows an inner scrollbar; - handles several elements on one page, each with its own session and surface;
- is safe to load more than once and can be included at the end of the body.
To render a surface into an element that appears later (a modal, a tab), add the element with the attributes and call window.MissLessSocial.mount(element). Elements present at load time are mounted automatically.
The plain iframe
Section titled “The plain iframe”<iframe src="https://social.missless.tel/embed/all?session=mle_5c1e9a7b3d2f8e4a6c0b9d1f7e3a5c2b" style="width:100%;height:720px;border:0" title="Social media" allow="clipboard-write"></iframe>Use one of the urls from the embed session response as src. Height is yours to manage; either give it a fixed height with the widget scrolling inside, or listen for resize yourself:
window.addEventListener('message', (e) => { if (e.origin !== 'https://social.missless.tel') return; if (e.data?.source !== 'missless-social' || e.data.event !== 'resize') return; document.querySelector('iframe[src*="social.missless.tel/embed"]').style.height = e.data.data.height + 'px';});All messages are described in Widget events.
Content Security Policy
Section titled “Content Security Policy”If your page sends a CSP, allow the frame and the script:
frame-src https://social.missless.tel;script-src 'self' https://social.missless.tel;The widget itself does not load anything from your origin and does not need cookies. Third-party cookie blocking does not affect it; the session token is in the URL.
In React
Section titled “In React”'use client';import { useEffect, useRef, useState } from 'react';
export function SocialWidget({ surface = 'all' }: { surface?: 'all' | 'composer' | 'calendar' | 'inbox' | 'accounts' }) { const [src, setSrc] = useState<string | null>(null); const frame = useRef<HTMLIFrameElement>(null);
useEffect(() => { fetch('/api/social/embed-session', { method: 'POST' }) .then((r) => r.json()) .then((s) => setSrc(s.urls[surface])); }, [surface]);
useEffect(() => { const onMessage = (e: MessageEvent) => { if (e.origin !== 'https://social.missless.tel' || e.data?.source !== 'missless-social') return; if (e.data.event === 'resize' && frame.current) frame.current.style.height = `${e.data.data.height}px`; }; window.addEventListener('message', onMessage); return () => window.removeEventListener('message', onMessage); }, []);
if (!src) return <div style={{ minHeight: 320 }} />; return <iframe ref={frame} src={src} title="Social media" style={{ width: '100%', height: 560, border: 0 }} />;}The route it calls is on the Embed sessions page.