You can handle multiple platforms embeds—like YouTube, X (Twitter), Instagram, Vimeo, and Spotify—with a single client-side JavaScript approach or a Ruby plugin hook.
Because platforms like X and Instagram use full interactive widgets rather than simple <iframe> elements, using JavaScript is usually the most reliable solution.
The Universal JavaScript + CSS Solution
This script checks paragraphs in your content for standalone URLs from supported platforms and swaps them out with their corresponding responsive embed HTML or platform scripts.
1. Add CSS for <iframe> embeds (YouTube, Spotify, Vimeo)
Add this to your CSS file (e.g., assets/css/style.scss):
/* Responsive container for video/audio standard iframes */
.responsive-embed-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 Aspect Ratio */
height: 0;
overflow: hidden;
max-width: 100%;
margin: 1.5rem 0;
}
.responsive-embed-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
/* Center social widgets like X & Instagram */
.social-embed-container {
display: flex;
justify-content: center;
margin: 1.5rem 0;
}
2. Add the JavaScript Parser
Add this script before </body> (e.g., in _includes/footer.html or _layouts/post.html).
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<script async src="https://www.instagram.com/embed.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const content = document.querySelector(".post-content") || document.querySelector("main");
if (!content) return;
const paragraphs = content.querySelectorAll("p");
paragraphs.forEach(p => {
const url = p.innerText.trim();
// Ensure the paragraph contains ONLY a URL
if (!url.match(/^https?:\/\/[^\s]+$/)) return;
let embedHTML = "";
// 1. YouTube
const ytMatch = url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
if (ytMatch) {
embedHTML = `
<div class="responsive-embed-container">
<iframe src="https://www.youtube-nocookie.com/embed/${ytMatch[1]}" allowfullscreen></iframe>
</div>`;
}
// 2. X (Twitter)
const xMatch = url.match(/(?:twitter\.com|x\.com)\/([a-zA-Z0-9_]+)\/status\/([0-9]+)/);
if (xMatch) {
embedHTML = `
<div class="social-embed-container">
<blockquote class="twitter-tweet"><a href="${url}"></a></blockquote>
</div>`;
}
// 3. Instagram
const igMatch = url.match(/(?:instagram\.com)\/(?:p|reel)\/([a-zA-Z0-9_-]+)/);
if (igMatch) {
embedHTML = `
<div class="social-embed-container">
<blockquote class="instagram-media" data-instgrm-permalink="${url}"></blockquote
</div>`;
}
// 4. Vimeo
const vimeoMatch = url.match(/vimeo\.com\/([0-9]+)/);
if (vimeoMatch) {
embedHTML = `
<div class="responsive-embed-container">
<iframe src="https://player.vimeo.com/video/${vimeoMatch[1]}" allowfullscreen></iframe>
</div>`;
}
// 5. Spotify (Tracks, Albums, Playlists)
const spotifyMatch = url.match(/open\.spotify\.com\/(track|album|playlist|episode)\/([a-zA-Z0-9]+)/);
if (spotifyMatch) {
embedHTML = `
<div style="margin: 1.5rem 0;">
<iframe src="https://open.spotify.com/embed/${spotifyMatch[1]}/${spotifyMatch[2]}"
width="100%" height="152" frameborder="0" allow="encrypted-media"></iframe>
</div>`;
}
// If a match was found, replace the <p> tag
if (embedHTML) {
p.outerHTML = embedHTML;
}
});
// Re-trigger social widgets rendering if necessary
if (window.twttr && window.twttr.widgets) window.twttr.widgets.load();
if (window.instgrm && window.instgrm.Embeds) window.instgrm.Embeds.process();
});
</script>
How it works in Markdown
Just drop raw URLs on their own lines:
Here is a YouTube video:
<div class="embed embed-video" data-embed="video" style="--embed-ratio: 56.25%;">
<div class="embed-video__inner">
<iframe src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ" title="YouTube video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen loading="lazy"></iframe>
</div>
</div>
Check out this post on X:
<div class="embed embed-twitter" data-embed="twitter">
<blockquote class="twitter-tweet" data-dnt="true">
<a href="https://twitter.com/i/status/1683528642000000000">View post on X</a>
</blockquote>
</div>
Or this Spotify track:
<div class="embed embed-spotify" data-embed="spotify">
<iframe style="border-radius:12px" src="https://open.spotify.com/embed/track/4cOdK2wGLETKBW3PvgPWqT" width="100%" height="152" frameborder="0" allowfullscreen allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy"></iframe>
</div>