This site allows you to get the content of posts and pages by adding either /embed/ or ?embed to the URL, optionally including the post title, author, and/or tags.This was inspired by a discussion in an Indieweb Homebrew Website Club Europe/London online meetup. I want to say shadowy web standards advocate Tantek Çelik brought it up, so, as these things tend to happen, I coded it up here while we were talking. It’s discussed on Indieweb’s wiki at https://indieweb.org/embed.What do you mean, ‘Embed’?Well, for instance, this post’s permalink is https://michaelkupietz.com/?p=10887. You can see just the text of this post’s content, without the sidebar and menus and other web page “furniture”, at https://michaelkupietz.com/embed/?p=10887 or https://michaelkupietz.com/embed/?p=10887&embed, so you can theoretically include this page’s content on your own site (long as you don’t mind ugly, 1993-looking unstyled HTML.) These are linked in the header of every page, as on this page you see Embed link up there in the small row of article info under the title.You can append ?title, ?author or ?tags parameters to the embed URL too, to include the page title, author, and/or post tags at the top of the embed content, respectively. Just do something like “https://michaelkupietz.com/blah/blah/embed/?title&author&tags”.How It Works Under The Hood (a WordPress-centric view)This is done by adding the following code to the theme’s functions.php file:// prevent stripping of /embed/ and embed parameters on redirects function preserve_embed_parts($redirect_url, $requested_url) { if ((strpos($requested_url, '/embed/') !== false || isset($_GET['embed'])) && $redirect_url !== $requested_url) { // If original had /embed/, add it to redirect if (strpos($requested_url, '/embed/') !== false && strpos($redirect_url, '/embed/') === false) { return rtrim($redirect_url, '/') . '/embed/'; } // If original had ?embed or &embed, add it to redirect if (isset($_GET['embed']) && strpos($redirect_url, 'embed') === false) { $separator = (strpos($redirect_url, '?') !== false) ? '&' : '?'; return $redirect_url . $separator . 'embed'; } } return $redirect_url; } add_filter('redirect_canonical', 'preserve_embed_parts', 10, 2); // Apply template for embed patterns function check_embed_template($template) { $uri = $_SERVER['REQUEST_URI']; $is_embed = ( strpos($uri, '/embed/') !== false || isset($_GET['embed']) ); if ($is_embed) { $new_template = locate_template(array('template-content-only.php')); if ($new_template) { return $new_template; } } return $template; } add_filter('template_include', 'check_embed_template'); template-content-only.phpThen in the theme folder, there’s a template ‘template-content-only.php’, which is basically as follows: <?php /* * Template Name: Content Only */ ?><!DOCTYPE html><html><head> <?php echo '<link rel="canonical" href="' . get_the_permalink() . '" /><!-- add canonical. -->' . "\n"; ?></head> <body><?php while (have_posts()): the_post(); if (isset($_GET["title"])) { echo '<h2 class="embed_title">'; echo get_the_title(); echo "</h2>"; } if (isset($_GET["tags"])) { echo '<style>.screen-reader-text.screen-reader-text {border: 0;clip: rect(1px,1px,1px,1px);-webkit-clip-path: inset(50%);clip-path: inset(50%);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute !important;width: 1px;word-wrap: normal !important;word-break: normal; }</style>'; echo "<i>Posted in "; /* [theme-specific code goes here to display post tags; omitted because you're not going to be able to use it, my theme is totally customized, so your theme's functions are different.] */ echo "</i>"; } if (isset($_GET['author'])) { echo '<p class="embed_author"><i>By '; echo get_the_author(); echo'</i></p>'; } the_content(); $pl = get_the_permalink(); echo '<p style="font-size:.75em";>Content originally from <a href="' . $pl . '" target="_new" rel="noopener">' . $pl . "</a>. © " . ($modified_date = esc_html(get_the_modified_date("Y")) . " Michael E. Kupietz</p>"); endwhile; // End of the loop. ?> </body> </html><?php But Wait, There’s More! A caveat.If you’re like me, and I think you are, you have Content Security Policy headers (I’d link to that, but there really aren’t any references that don’t make it sound much more complicated than it is) set up on your site to make sure nobody can inject scripts or wrap your site in an invisible iframe and clickjack your mom while she thinks she’s looking directly at your site. Well, like all good security measures, this will trip you up, because if you have it set right, it may prevent the end goal of embedding from working at all, because nobody will be allowed to put your site in an iframe.This will happen if you have something like this in your .htaccess file:Header set Content-Security-Policy "[a bunch of rules & garbage here]; frame-ancestors 'self'". You may have none instead of .So we want to bend the rules, so if the url ends in /embed/ or has an ?embed url parameter, the frame-ancestors restrictions are lifted just for that page.We do this by wrapping that line with the following, wherever in your .htaccess file the security headers are defined: <If "%{THE_REQUEST} =~ m|/embed/?(?:[ ?#])| || %{QUERY_STRING} =~ m#(?:^|&)embed(?:&|$|=)#"> Header set Content-Security-Policy "[all your original rules and junk go here except for the frame-ancestors part]; frame-ancestors 'self' *" </If> <Else> Header set Content-Security-Policy "[a bunch of rules & garbage here]; frame-ancestors 'self'" [this is just your original Header set Content-Security-Policy line, unchanged from what it was before because we want it to still apply to everything except the special Embed pages.] </Else> Huge web nerds will notice I used %{THE_REQUEST} instead of %{REQUEST_URI} like ChatGPT told you to when you wimped out and asked it how to do this. This is because ChatGPT doesn’t know that there’s a bug in Apache where %{REQUEST_URI} doesn’t work right in conditionals and will always fail and cause you to spend an entire day going in circles, rending your clothes and wailing in despair at the dark gods who came up with this system. The sole reference I’ve seen to this is at https://processwire.com/talk/topic/23000-apache2-blocks-dont-work-with-regex-matches-against-the-request_uri-variable/, as was kindly pointed out to me by one of the helpful Indieweb folks, but sure enough, the suggestion there, to use THE_REQUEST instead, worked.So, AnyhooThis gives you a very easy way to pull my content by whatever embedding method you prefer,e.g.:<iframe style="width: 100%; height: 400px;" src="https://michaelkupietz.com/embed/?p=10887&title&tags"></iframe>Which, being this very page, is displayed on the front end as:I call this “The Infinity Iframe”. Mike Kupietz , a reluctant scion of the postmodern age, is larger on the inside than the outside: perhaps not a composer, but a producer and arranger of sounds; nor a writer, but an avid writer-down; an occasional author of doggerel; an erstwhile urban hermit; and privately a man of very great ardor. He is, if now resigned to never succeeding at those personal and artistic pursuits he holds most dear, unwavering in his determination to fail at them as entertainingly as possible. He is currently in what he calls the "red bathrobe period" of his life. If you're wondering what all this has to do with FileMaker development or IT consulting: you done taken the wrong turn, this river don't go to Aintry—Mike's professional services are on his San Francisco FileMaker Pro consulting website. View All PostsPost navigationPrevious Post /TriviaNext Post/Not