TinyMCE embed integration

Let editors paste a URL and insert embed HTML from OpenGraph.io, including fallback cards when native oEmbed is unavailable.

Architecture

TinyMCE runs in the browser, but do not expose your App ID client-side in production. Proxy the oEmbed request through your backend, then return html to the editor.

The oEmbed html field is designed to be inserted directly into rich-text content. Sanitize according to your trust model if URLs are user-submitted.

Custom toolbar button

TinyMCE setup
tinymce.init({
  selector: '#editor',
  toolbar: 'link ogembed',
  setup(editor) {
    editor.ui.registry.addButton('ogembed', {
      text: 'Embed URL',
      onAction: async () => {
        const url = prompt('Paste URL to embed');
        if (!url) return;
        const res = await fetch('/api/embed-proxy', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ url }),
        });
        const data = await res.json();
        if (data.html) editor.insertContent(data.html);
      },
    });
  },
});

Backend proxy (Node.js example)

/api/embed-proxy
app.post('/api/embed-proxy', async (req, res) => {
  const { url } = req.body;
  const og = await fetch(
    `https://opengraph.io/api/3.0/oembed?url=${encodeURIComponent(url)}&app_id=${process.env.OPENGRAPH_APP_ID}`
  );
  const data = await og.json();
  res.json({ html: data.html, source: data.source, embed_id: data.embed_id });
});

Optional: maxwidth for layout

Pass maxwidth and maxheight to match your editor column width:

...&maxwidth=640&maxheight=480

See also