Skip to content

Drop-in

Two ways to put a surface on a page. The loader is less work; the plain iframe gives you full control.

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 with width: 100%, no border, and the right src;
  • listens for resize messages 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.

<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.

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.

components/SocialWidget.tsx
'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.