Embeds in Hub Content
Purple Hub
Summary
The Purple Hub supports inserting content blocks from external web sources, so called ‘embeds’. For instance, can you insert a video block from a social media platform like YouTube. Doing this, the block will display the ‘live’ content from that external provider in your Purple Hub content.
Read this guide to learn how to add third party content via the embed block in to an article in Purple Hub.
Description
The Purple Hub uses the WordPress standard functionality for embedding content. This function allows you to add videos, images, tweets, audio, and other content from third-party services into your Purple Hub content by embedding.
Embedding content has the advantage that you don’t need to upload the content to your Purple Hub. You can insert the live content from a third party website be only inserting the link to your port or page in Purple Hub.
To do so, you can add the Embed Block to your content, paste the URL from the third-party site that you want to embed the content such as YouTube, Vimeo, TED, etc. on your post or page.
Embeds only work for a defined selection of third-party providers, find the list of supported embeds in the WordPress documentation.
Learn more about Embeds in the external WordPress documentation.
Instagram, Facebook and Threads embeds
Paste the URL of a public Instagram, Facebook or Threads post into an Embed Block, or choose the Instagram, Facebook or Threads variant from the block list. No account or access token is needed. Only public posts can be embedded, and these embeds always load live from Meta, so they need a network connection and cannot be shown offline.
In apps and on Purple web, these embeds are rendered by a script that is part of the app theme. The theme is not updated automatically. Apps whose theme was added to the dynamic resources before this support was available show Instagram embeds as a grey placeholder, Facebook embeds not at all and Threads embeds as a plain link. To update it, download the theme from App Themes in the Hub and merge its files into the app's existing dynamic resources. The download only contains the Hub part of the dynamic resources, so never upload it on its own as the app's dynamic resources. If you do not want to update the whole theme, add the example script below to the theme's JavaScript in the dynamic resources instead. For how to update dynamic resources, see Deploy dynamic resources via Purple Manager. Consent for Meta content is handled by your project's consent management platform.
Articles published before this support was available still contain the broken embed. Republish them to update the embed.
If you render Hub content in a frontend you built yourself, you have to load Meta's embed scripts there. The published content contains the embed markup but no script tags, so without the scripts the embeds show up as plain, unstyled quotes.
You can recognise these embeds by the providerNameSlug of the core/embed block: instagram, facebook or threads. Instagram needs https://www.instagram.com/embed.js, Threads needs https://www.threads.com/embed.js and Facebook needs https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v25.0. Load the Instagram and Threads scripts before the Facebook script, also on pages where only a later article contains an Instagram or Threads embed: once the Facebook script has run, the other two do nothing. The scripts only look for embeds once when they load, so for content you insert afterwards, call window.instgrm.Embeds.process() (Instagram and Threads) or window.FB.XFBML.parse() (Facebook).
The following script does all of this and also handles content inserted later. It is the same script the app theme contains, so you can use it as it is:
;(function () {
// Purple web runs the theme scripts again on every content view
if (window.metaEmbedsLoaderStarted) {
return
}
window.metaEmbedsLoaderStarted = true
const embedSelector = "blockquote.instagram-media, blockquote.text-post-media, .fb-post, .fb-video"
// Instagram and Threads do nothing once the Facebook script has run, so they have to load first
const scriptSources = [
"https://www.instagram.com/embed.js",
"https://www.threads.com/embed.js",
"https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v25.0",
]
let scriptsAdded = false
function containsEmbed(node) {
return node instanceof Element && (node.matches(embedSelector) || node.querySelector(embedSelector) !== null)
}
function processMetaEmbeds() {
if (scriptsAdded) {
window.instgrm?.Embeds.process()
window.FB?.XFBML.parse()
return
}
scriptsAdded = true
for (const scriptSource of scriptSources) {
const script = document.createElement("script")
script.src = scriptSource
// Downloaded in parallel, executed in this order
script.async = false
document.body.appendChild(script)
}
}
if (document.querySelector(embedSelector) !== null) {
processMetaEmbeds()
}
new MutationObserver((mutations) => {
const embedAdded = mutations.some((mutation) => [...mutation.addedNodes].some(containsEmbed))
if (embedAdded) {
processMetaEmbeds()
}
}).observe(document.documentElement, { childList: true, subtree: true })
})()Example (video) embed in Hub article
