<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>WordPress &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Tue, 14 Apr 2026 22:11:25 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>WordPress &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[RSS Club for WordPress]]></title>
		<link>https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 16 Apr 2026 11:34:10 +0000</pubDate>
				<category><![CDATA[[RSS Club]]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[RSS Club]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=70024</guid>

					<description><![CDATA[What if I told you there was a secret social network, hidden in plain sight? If you&#039;re reading this message, you&#039;re now a member of RSS Club!  RSS Club is a series of posts which are only visible to RSS / Atom subscribers. Like you 😃  If you want this for your own WordPress site, here&#039;s what you&#039;ll need:   A blog post which is only visible in RSS / Atom. Which has no HTML rendering on your site. A…]]></description>
										<content:encoded><![CDATA[<p>What if I told you there was a <em>secret</em> social network, hidden in plain sight? If you're reading this message, you're now a member of <a href="https://daverupert.com/rss-club/">RSS Club</a>!</p>

<p>RSS Club is a series of posts which are <em>only</em> visible to RSS / Atom subscribers. Like you 😃</p>

<p>If you want this for your own WordPress site, here's what you'll need:</p>

<ol>
<li>A blog post which is <em>only</em> visible in RSS / Atom.</li>
<li>Which has no HTML rendering on your site.</li>
<li>And cannot be found in your site's search.</li>
<li>Nor via search engines.</li>
<li>Also, doesn't appear on your mailing list.</li>
<li>Does not get shared or syndicated to the Fediverse.</li>
</ol>

<p>(This is a <em>bit</em> more strict than <a href="https://daverupert.com/2018/01/welcome-to-rss-club/">the original rules</a> which allow for web rendering and being found via a search engine.)</p>

<h2 id="start-with-a-category"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#start-with-a-category">Start With A Category</a></h2>

<p>The easiest way to do this in WordPress is via a category - <em>not</em> a tag.</p>

<p>After creating a category on your blog, click the edit link. You will see in the URl bar a <code>tag_id</code>.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/Category-ID.webp" alt="Screenshot of the WordPress website." width="1283" height="877" class="aligncenter size-full wp-image-70025">

<p>Whenever you want to make an RSS-exclusive post, you select the category before you publish.</p>

<h2 id="disable-display"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#disable-display">Disable Display</a></h2>

<p>This code stops any page in the RSS Club category from being displayed on the web.</p>

<pre><code class="language-php">function rss_club_post_blocker(): void {
    if (    is_singular( "post" )
        &amp;&amp;  has_category( "rss-club" )
        &amp;&amp; !current_user_can( "edit_posts" ) )
    {
        status_header( 403 );
        echo "You must be a member of RSS Club to view this content.";
        exit;
    }
}
add_action( "template_redirect", "rss_club_post_blocker" );
</code></pre>

<p>Editors can still see it, but everyone else gets a blocked message.</p>

<h2 id="remove-from-site-search-and-sitemap"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#remove-from-site-search-and-sitemap">Remove From Site Search and SiteMap</a></h2>

<p>Here's a snippet to stick in your <code>functions.php</code> - it removes the category from any queries unless it is for the admin pages or the RSS feeds.</p>

<pre><code class="language-php">//  Remove the RSS Club category from search results.
//  $query is passed by reference
function rss_club_search_filter( \WP_Query $query ): void {
    //  Ignore admin screens.
    if ( !is_admin() &amp;&amp; !is_feed() ) {
        //  Find the RSS-Club category ID.
        $category = get_category_by_slug( "rss-club" );

        //  Remove it from the search results.
        if ( $category ) {
            $query-&gt;set( "category__not_in", [$category-&gt;term_id] );
        }       
    }
}
add_action( "pre_get_posts", "rss_club_search_filter" );
</code></pre>

<p>This code also redacts that category from the build-in sitemap. Note - the <em>name</em> of the category still shows up in the XML, but it leads to a 404.</p>

<h2 id="exclude-from-email-and-social-media-rss-feeds"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#exclude-from-email-and-social-media-rss-feeds">Exclude From Email and Social Media RSS Feeds</a></h2>

<p>My mailing list and social media posts are fed from RSS. So how do remove an entire category from an RSS feed?</p>

<p>Simple! Append <code>?cat=-1234</code> to the end!</p>

<p>A negative category ID will remove the category from being displayed. So my email subscribers won't see the RSS only content. Of course, they get email-only exclusive posts, so don't feel too bad for them 😊</p>

<h2 id="fediverse-exclusion"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#fediverse-exclusion">Fediverse Exclusion</a></h2>

<p>The manual way is easiest. Assuming you have the <a href="https://github.com/Automattic/wordpress-activitypub/">ActivityPub plugin</a> and a the <a href="https://github.com/janboddez/share-on-mastodon/">Share On Mastodon plugin</a>, you can unselect the sharing options before publishing.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/No-Masto.webp" alt="Screenshot showing no sharing selected." width="600" class="aligncenter size-full wp-image-70028">

<p>If you think you might forget to toggle those boxen, there is <a href="https://github.com/janboddez/share-on-mastodon/issues/31">a filter for the share plugin</a>:</p>

<pre><code class="language-php">function rss_club_mastodon_filter( bool $is_enabled, int $post_id ): bool {
    global $exclude;
    if ( has_category( $exclude, $post_id ) ) {
        return false;
    }
    return $is_enabled;
}
add_filter( "share_on_mastodon_enabled", "rss_club_mastodon_filter", 10, 2 );
</code></pre>

<p>Similarly, there's a <a href="https://github.com/Automattic/wordpress-activitypub/blob/730d0ae51ce77be28439969dd9788c745a46681f/includes/functions-post.php#L77">filter for the ActivityPub plugin</a>:</p>

<pre><code class="language-php"><br>function rss_club_activitypub_filter( bool $disabled, \WP_Post $post ): bool 
{
    global $exclude;
    if ( has_category( $exclude, $post ) ) {
        return true;
    }

    return $disabled;
}
add_filter( "activitypub_is_post_disabled", "rss_club_activitypub_filter", 10, 2 );
</code></pre>

<h2 id="enjoy"><a href="https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/#enjoy">Enjoy!</a></h2>

<p>If you've set up your own RSS Club feed, <a href="https://edent.tel/">drop me a line</a> so I can subscribe 😊</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70024&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/04/rss-club-for-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Did WordPress VIP leak my phone number?]]></title>
		<link>https://shkspr.mobi/blog/2026/04/did-wordpress-vip-leak-my-phone-number/</link>
					<comments>https://shkspr.mobi/blog/2026/04/did-wordpress-vip-leak-my-phone-number/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 11:34:43 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[automattic]]></category>
		<category><![CDATA[gdpr]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=69804</guid>

					<description><![CDATA[As discussed in my last blog post, the scumsuckers at Apollo.io have been giving out my personal details.  Not only did they have my email address, they also had a copy of one of my phone numbers. I asked them where they got it from and they said:  Your phone number came from Parsely, Inc (wpvip.com) one of our customers who participates in our customer contributor network by sharing their…]]></description>
										<content:encoded><![CDATA[<p>As discussed <a href="https://shkspr.mobi/blog/2026/04/someone-at-browserstack-is-leaking-users-email-address/">in my last blog post</a>, the scumsuckers at Apollo.io have been giving out my personal details.</p>

<p>Not only did they have my email address, they also had a copy of one of my phone numbers. I asked them where they got it from and they said:</p>

<blockquote><p>Your phone number came from Parsely, Inc (wpvip.com) one of our customers who participates in our customer contributor network by sharing their business contacts with the Apollo platform.</p></blockquote>

<p>I've never done any business with <a href="https://www.parse.ly/">Parsely</a>. They have no reason to have my phone number and <em>absolutely</em> no permission to share it with other organisations.</p>

<p>Back in 2021, <a href="https://wpvip.com/blog/parse-ly-is-now-a-core-part-of-wordpress-vips-platform/">Parsely became part of WordPress VIP</a>. Ah yes, our old "friends" at Automattic with their <a href="https://shkspr.mobi/blog/2024/12/is-wordpress-org-gdpr-compliant/">somewhat lax attitude to privacy</a>.</p>

<p>I took advantage of <a href="https://wpvip.com/vip-and-the-gdpr/">WordPress VIP's GDPR policy</a> and sent a terse but polite "Hey, WTAF?" to them. Their response was quick:</p>

<blockquote><p>Thanks for reaching out. We are currently investigating our systems to locate any personal data regarding your request. We appreciate your patience.</p></blockquote>

<p>After a bit of prodding, they eventually replied with:</p>

<blockquote><p>It appears that we obtained your contact information as a result of a meeting you had with a representative for the WPScan service around August 5, 2022. WPScan is owned by our parent company Automattic.</p>

<p>We have no record of Parsely, Inc. (which is no longer in existence) or WPVIP Inc. (the owner of the Parse.ly service) having any relationship with Apollo.io.</p>

<p>We also have no record of Parsely, Inc. or WPVIP Inc. having sold or otherwise provided your information to any third party.</p></blockquote>

<p>I have no memory and no record of meeting anyone from WPScan - although I concede it is possible I did as part of a previous job.</p>

<p>But even if it was in an email signature when I contacted them that still doesn't explain how it made its way to Apollo for them to give to spammers everywhere. Was it a hack? A data leak? A treacherous employee? A deliberate sale? A sneaky app update? Or maybe just Apollo lying to me.</p>

<p>I don't care any more. I'm just so tired of shitty companies treating personal data as a commodity to be traded, sold, repackaged, and abused.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=69804&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/04/did-wordpress-vip-leak-my-phone-number/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Adding human.json to WordPress]]></title>
		<link>https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 26 Mar 2026 12:34:52 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[humans]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=69190</guid>

					<description><![CDATA[Every few years, someone reinvents FOAF. The idea behind Friend-Of-A-Friend is that You can say &#34;I, Alice, know and trust Bob&#34;. Bob can say &#34;I know and trust Alice. I also know and trust Carl.&#34; That social graph can be navigated to help understand trust relationships.  Sometimes this is done with complex cryptography and involves key-signing ceremonies. Other times it involves byzantine XML RDF.…]]></description>
										<content:encoded><![CDATA[<p>Every few years, someone reinvents <abbr title="Friend of a friend">FOAF</abbr>. The idea behind Friend-Of-A-Friend is that You can say "I, Alice, know and trust Bob". Bob can say "I know and trust Alice. I also know and trust Carl." That social graph can be navigated to help understand trust relationships.</p>

<p>Sometimes this is done with complex cryptography and involves key-signing ceremonies. Other times it involves byzantine <a href="http://ldodds.com/foaf/foaf-a-matic.html">XML RDF</a>. Or you can use the baroque <a href="https://gmpg.org/xfn/">XHTML Friends Network</a>.</p>

<p>None of those have been widely adopted. Perhaps it's because PGP is a usability nightmare, XML is out of fashion, or because these relationships mostly live in silos like Facebook and LinkedIn, or just that people value their privacy and don't want to expose their social graph any more than they have to.</p>

<p>Enter a new contender into the ring - <a href="https://codeberg.org/robida/human.json">human.json</a> - it describes itself as:</p>

<blockquote><p>a lightweight protocol for humans to assert authorship of their site content and vouch for the humanity of others. It uses URL ownership as identity, and trust propagates through a crawlable web of vouches between sites.</p></blockquote>

<p>It looks like this:</p>

<pre><code class="language-json">{
  "version": "0.1.1",
  "url": "https://shkspr.mobi/blog/",
  "vouches": [
    {
      "url": "https://neilzone.co.uk/",
      "vouched_at": "2026-03-20"
    },
    {
      "url": "https://ohhelloana.blog/",
      "vouched_at": "2026-03-20"
    }
  ]
}
</code></pre>

<p>That says that I assert my own blog is written by a human, and that I vouch that my friends Neil and Ana write their own content.</p>

<p>Now, obviously there's no way that I can <em>prove</em> my blog posts are written by an organic, vegan-fed, human. And, while I know and trust the friends I've met AFK, I don't have any special insight into their creative processes. If I suspect them of being synthetic clankers, I can disavow their sites by removing them from my <code>human.json</code> file.</p>

<h2 id="adding-to-wordpress"><a href="https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/#adding-to-wordpress">Adding to WordPress</a></h2>

<p>There's an easy way and a hard way. The easy way it to just hand-write a JSON file and upload it to your website. BORING!</p>

<p>To start with, you'll need to add some code to your HTML's head. Stick this in your <code>index.php</code></p>

<pre><code class="language-html">&lt;link rel=human-json href=https://example.com/json/human.json&gt;
</code></pre>

<p>Next, add this to your <code>functions.php</code> or wherever you set your weird options:</p>

<pre><code class="language-php">//  Add rewrite rule for /json and /json/{something}
add_action( "init", function () {
    add_rewrite_rule(
        '^json(?:/([^/]+))?/?$',    //  Matches /json and /json/{something}
        'index.php?pagename=json&amp;json_param=$matches[1]',
        "top"
    );
});

//  Register custom query variable
add_filter( "query_vars" , function ($vars) {
    $vars[] = "json_param";
    return $vars;
});
</code></pre>

<p>That creates a rewrite so that <code>/json/whatever</code> will be intercepted. For now, this only deals with human.json - but there may be more weird JSON things you want to support later. Hurrah for over-engineering!</p>

<p>Next, add this:</p>

<pre><code class="language-php">add_action( "template_redirect", function() {
    if ( get_query_var( "json_param" ) &amp;&amp; "human.json" == get_query_var( "json_param" ) ) {
        $data = [
            "version" =&gt; "0.1.1",
                "url" =&gt; esc_url( home_url() ),
            "vouches" =&gt; [
                [
                           "url" =&gt; "https://friend.example.com",
                    "vouched_at" =&gt; "2026-03-20"
                ],
                [
                           "url" =&gt; "https://whatever.example",
                    "vouched_at" =&gt; "2026-03-20"
                ],

            ]
        ];
        //  Headers to make sure it all works.
        header( "Access-Control-Allow-Origin: *" );
        wp_send_json( $data, 200 );
    }
} );
</code></pre>

<p>That intercepts the request, generates some JSON, then serves it with the correct content type and CORS headers.</p>

<p>You may need to refresh your redirects. Easiest way is to go to your blog's admin page and choose Settings → Permalinks, then hit <kbd>Save</kbd></p>

<h2 id="over-over-engineering"><a href="https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/#over-over-engineering">Over over engineering</a></h2>

<p>This takes a list of your human friends, deduplicates them, sorts them alphabetically, and changes the vouch date to that of when you last updated the files.</p>

<pre><code class="language-php">add_action( "template_redirect", function() {
    if ( get_query_var( "json_param" ) ) {
        // https://codeberg.org/robida/human.json
        if ( strcasecmp( "human.json", get_query_var( "json_param" ) ) == 0 ) {

            //  People who I know to be human.
            $humans = array_unique([
                "https://neilzone.co.uk/",
                "https://ohhelloana.blog/",
                "https://example.com/",
            ]);

            sort( $humans );

            //  When was this file updated?
            //  RFC 3339 date format.
            $modified = date( "Y-m-d", filemtime( __FILE__ ) );

            foreach ( $humans as $human ) {
                $vouches[] = [ "url" =&gt; $human, "vouched_at" =&gt; $modified ];
            }

            $data = [
                "version" =&gt; "0.1.1",
                    "url" =&gt; esc_url( home_url() ),
                "vouches" =&gt; $vouches
            ];

            //  Headers to make sure it all works.
            header( "Access-Control-Allow-Origin: *" );
            wp_send_json( $data, 200, JSON_PRETTY_PRINT );
        } else {
            //  No valid parameter
            wp_send_json( null,  404, JSON_PRETTY_PRINT );
        }
    }
} );
</code></pre>

<h2 id="is-it-worth-it"><a href="https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/#is-it-worth-it">Is it worth it?</a></h2>

<p>I don't know.</p>

<p>Perhaps no one will use this. Or perhaps all my friends will turn out to be poorly constructed Turing machines. Or maybe a better standard will come along.</p>

<p>Either way, I think it is nifty and am happy to support it.</p>

<p>You can <a href="https://codeberg.org/robida/human.json">read more about human.json on CodeBerg</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=69190&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/03/adding-human-json-to-wordpress/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A big list of things I disable in WordPress]]></title>
		<link>https://shkspr.mobi/blog/2025/11/a-big-list-of-things-i-disable-in-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2025/11/a-big-list-of-things-i-disable-in-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 30 Nov 2025 12:34:23 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=63344</guid>

					<description><![CDATA[There are many things I like about the WordPress blogging software, and many things I find irritating. The most annoying aspect is that WordPress insists that its way is the best and there shall be no deviance. That means a lot of forced cruft being injected into my site. Headers that bloat my page size, Gutenberg stuff I&#039;ve no use for, and ridiculous editorial decisions.  To double-down on the…]]></description>
										<content:encoded><![CDATA[<p>There are many things I like about the WordPress blogging software, and many things I find irritating. The most annoying aspect is that WordPress insists that its way is the best and there shall be no deviance. That means a <em>lot</em> of forced cruft being injected into my site. Headers that bloat my page size, Gutenberg stuff I've no use for, and <a href="https://developer.wordpress.org/reference/functions/capital_p_dangit/">ridiculous editorial decisions</a>.</p>

<p>To double-down on the annoyance, there's no simple way to turn them off. In part, that is due to the "<a href="https://wordpress.org/about/philosophy/">WordPress Philosophy</a>":</p>

<blockquote><p><strong>Decisions, not options</strong></p>

<p>[…] Every time you give a user an option, you are asking them to make a decision. When a user doesn’t care or understand the option this ultimately leads to frustration.</p></blockquote>

<p>I broadly agree with that. Having hundreds of options is a burden for users and a nightmare for maintainers. Do please read this <a href="https://tommcfarlin.com/wordpress-philosophy-decisions-not-options/">excellent discussion from Tom McFarlin for a more detailed analysis</a>.</p>

<p>But I <em>want</em> to turn things off. Luckily, there is a way. If you're a developer, you can remove a fair number of these "enforced" decisions. Add the following to your theme's <code>functions.php</code> file and watch the mandatory WordPress bloat whither away.  I've commented each removal and, where possible, given a source for more information.  Feel free to leave a comment suggesting how this script can be improved and simplified.</p>

<pre><code class="language-php">//  Remove mandatory classic theme.
function disable_classic_theme_styles() {
    wp_deregister_style( "classic-theme-styles" );
    wp_dequeue_style(    "classic-theme-styles" );
}
add_action( "wp_enqueue_scripts", "disable_classic_theme_styles" );

//  Remove WP Emoji.
//  http://www.denisbouquet.com/remove-wordpress-emoji-code/
remove_action( "wp_head",             "print_emoji_detection_script", 7 );
remove_action( "wp_print_styles",     "print_emoji_styles"              );
remove_action( "admin_print_scripts", "print_emoji_detection_script"    );
remove_action( "admin_print_styles",  "print_emoji_styles"              );
//  https://wordpress.org/support/topic/remove-the-new-dns-prefetch-code/
add_filter( "emoji_svg_url", "__return_false" );

//  Stop emoji replacement with images in RSS / Atom Feeds
//  https://danq.me/2023/09/04/wordpress-stop-emoji-images/
remove_filter( "the_content_feed", "wp_staticize_emoji" );
remove_filter( "comment_text_rss", "wp_staticize_emoji" );

//  Remove automatic formatting.
//  https://css-tricks.com/snippets/wordpress/disable-automatic-formatting/
remove_filter( "the_content",  "wptexturize" );
remove_filter( "the_excerpt",  "wptexturize" );
remove_filter( "comment_text", "wptexturize" );
remove_filter( "the_title",    "wptexturize" );

//  More formatting crap.
add_action("init", function() {
    remove_filter( "the_content", "convert_smilies", 20 );
    foreach ( array( "the_content", "the_title", "wp_title", "document_title" ) as $filter ) {
        remove_filter( $filter, "capital_P_dangit", 11 );
    }
    remove_filter( "comment_text", "capital_P_dangit", 31 );    //  No idea why this is separate
    remove_filter( "the_content",  "do_blocks", 9 );
}, 11);

//  Remove Gutenberg Styles.
//  https://wordpress.org/support/topic/how-to-disable-inline-styling-style-idglobal-styles-inline-css/
remove_action( "wp_enqueue_scripts", "wp_enqueue_global_styles" );

//  Remove Gutenberg editing widgets.
//  From https://wordpress.org/plugins/classic-widgets/
//  Disables the block editor from managing widgets in the Gutenberg plugin.
add_filter( "gutenberg_use_widgets_block_editor", "__return_false" );
//  Disables the block editor from managing widgets.
add_filter( "use_widgets_block_editor", "__return_false" );

//  Remove Gutenberg Block Library CSS from loading on the frontend.
//  https://smartwp.com/remove-gutenberg-css/
function remove_wp_block_library_css() {
    wp_dequeue_style( "wp-block-library"       );
    wp_dequeue_style( "wp-block-library-theme" );
    wp_dequeue_style( "wp-components"          );
}
add_action( "wp_enqueue_scripts", "remove_wp_block_library_css", 100 );

//  Remove hovercards on comment links in admin area.
//  https://wordpress.org/support/topic/how-to-disable-mshots-service/#post-12946617
add_filter( "akismet_enable_mshots", "__return_false" );

//  Remove Unused Plugin code.
function remove_plugin_css_js() {
    wp_dequeue_style( "image-sizes" );
}
add_action( "wp_enqueue_scripts", "remove_plugin_css_js", 100 );

//  Remove WordPress forced image size
//  https://core.trac.wordpress.org/ticket/62413#comment:40
add_filter( "wp_img_tag_add_auto_sizes", "__return_false" );

//  Remove &lt;img&gt; enhancements
//  https://developer.wordpress.org/reference/functions/wp_filter_content_tags/
remove_filter( "the_content",  "wp_filter_content_tags", 12 );

//  Stop rewriting http:// URls for the main domain.
//  https://developer.wordpress.org/reference/hooks/wp_should_replace_insecure_home_url/
remove_filter( "the_content", "wp_replace_insecure_home_url", 10 );

//  Remove the attachment stuff
//  https://developer.wordpress.org/news/2024/01/building-dynamic-block-based-attachment-templates-in-themes/
remove_filter( "the_content", "prepend_attachment" );

//  Remove the block filter
remove_filter( "the_content", "apply_block_hooks_to_content_from_post_object", 8 );

//  Remove browser check from Admin dashboard.
//  https://core.trac.wordpress.org/attachment/ticket/27626/disable-wp-check-browser-version.0.2.php
if ( !empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
    add_filter( "pre_site_transient_browser_" . md5( $_SERVER["HTTP_USER_AGENT"] ), "__return_null" );
}

//  Remove shortlink.
//  https://stackoverflow.com/questions/42444063/disable-wordpress-short-links
remove_action( "wp_head", "wp_shortlink_wp_head" );

//  Remove RSD.
//  https://wpengineer.com/1438/wordpress-header/
remove_action( "wp_head", "rsd_link" );

//  Remove extra feed links.
//  https://developer.wordpress.org/reference/functions/feed_links/
add_filter( "feed_links_show_comments_feed", "__return_false" );
add_filter( "feed_links_show_posts_feed",    "__return_false" );

//  Remove api.w.org link.
//  https://wordpress.stackexchange.com/questions/211467/remove-json-api-links-in-header-html
remove_action( "wp_head", "rest_output_link_wp_head" );
//  https://wordpress.stackexchange.com/questions/211817/how-to-remove-rest-api-link-in-http-headers
//  https://developer.wordpress.org/reference/functions/rest_output_link_header/
remove_action( "template_redirect", "rest_output_link_header", 11, 0 );
</code></pre>

<p>You can find the latest version of <a href="https://gitlab.com/edent/blog-theme/-/blob/master/includes/remove.php">my debloat script</a> in my theme's repo.</p>

<p>If there are other things you find helpful to remove, or a better way to organise this file, please drop a comment in the box.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63344&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/11/a-big-list-of-things-i-disable-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Reasonably accurate, privacy conscious, cookieless, visitor tracking for WordPress]]></title>
		<link>https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 11 Sep 2025 11:34:39 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=63158</guid>

					<description><![CDATA[I am vain. I like to know which of my blog posts have &#34;done numbers&#34;. I get a little thrill knowing that an old post I wrote has been read by someone in a land I&#039;ve never visited. I&#039;m curious and want to know if a newsletter has linked to me.  At the same time, I don&#039;t want to know too much about people. I don&#039;t want to stalk them around the web. I refuse to care how long they spend with me. I…]]></description>
										<content:encoded><![CDATA[<p>I am vain. I like to know which of my blog posts have "done numbers". I get a little thrill knowing that an old post I wrote has been read by someone in a land I've never visited. I'm curious and want to know if a newsletter has linked to me.</p>

<p>At the same time, I don't want to know <em>too</em> much about people. I don't want to stalk them around the web. I refuse to care how long they spend with me. I can't be bothered setting up a foolproof system that captures 100% accurate information.</p>

<p>After trying several analytics plugins for WordPress, I've decided to have a go at writing my own<sup id="fnref:learn"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#fn:learn" class="footnote-ref" title="I enjoy learning. If you're about to say &quot;Why not just install…&quot; then you've missed the point. I like understanding how things work, I get joy from discovering some new function, my brain feels happy…" role="doc-noteref">0</a></sup>.</p>

<p>Before embarking on this, please do read "<a href="https://blog.yossarian.net/2023/12/24/You-dont-need-analytics-on-your-blog">You Don't Need Analytics on Your Blog</a>" and the slightly more provocative "<a href="https://www.thisdaysportion.com/posts/contra-analytics/">You do not need “analytics” for your blog because you are neither a military surveillance unit nor a commodity trading company</a>". Both give excellent examples of why this is at best foolish and at worse injurious.  Proceed with caution in your heart.</p>

<h2 id="background"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#background">Background</a></h2>

<p>As a consequence of the way the web works, every time you click on a link the website's owner gets the following pieces of information.</p>

<ul>
<li>The time you clicked,</li>
<li>The page you visited,</li>
<li>The name of the web browser you use,</li>
<li>The URl of the page which you clicked to get here,</li>
<li>The IP address your computer has.</li>
</ul>

<p>There are a few other things sent along but they're not interesting to me.</p>

<p>Using that information, I can construct a reasonably accurate view of how many times a post has been viewed and how many people viewed it.</p>

<h2 id="defining-a-page-view"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#defining-a-page-view">Defining a page view</a></h2>

<p>If a web page is loaded, that counts as a view. I'm not going to track whether the user stayed for more than 30 seconds or closed their browser in disgust after reading the headline. If the page is loaded, that's a view.</p>

<p>But what if one person repeatedly hits refresh on the same post?  To deal with that, I'll need a concept of a visitor.</p>

<h2 id="defining-a-visitor"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#defining-a-visitor">Defining a visitor</a></h2>

<p>The "normal" way of doing things is to stick a cookie in the user's browser and track them that way. I can't be bothered with that. And, besides, it doesn't account for a person reading on their laptop and then moving to their phone.</p>

<p>So I'm going to use a proxy by creating a cryptographic hash of the visitor's IP address and the browser's User Agent string.</p>

<p>Of course, a household might have one IP address and multiple people with the same phone. But, equally, one person might rove over several WiFi networks in the course of one browsing session, getting a different IP each time.</p>

<p>The aim is to be <em>reasonably</em> accurate.</p>

<p>Hashing the contents means I don't need to store the user's IP address. Once hashed, the information becomes a string like <code>db050e7b853e5856</code> which is functionally impossible to <a href="https://www.techsolvency.com/passwords/dehashing-reversing-decrypting/">crack</a> back to an IP address &amp; UA string<sup id="fnref:orisit"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#fn:orisit" class="footnote-ref" title="Or is it? There are 4 billion IPv4 addresses - although slightly fewer in actual use. Creating a rainbow table with 4 billion rows is possible if I was just using IP addresses. But there are an…" role="doc-noteref">1</a></sup>.</p>

<p>This also means that I can redefine the concept of a page view. If the same visitor refreshed the page multiple times, it will only count as a single visit.</p>

<p>I'll reset the counter at midnight in my local timezone. If someone visits just before midnight and then just after, it'll count as two visits. Oh well.</p>

<h2 id="where-did-they-come-from"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#where-did-they-come-from">Where did they come from?</a></h2>

<p>Generally speaking, there are two ways that visitors share their referrer. One is the "referer" header (yes, it is misspelled). It contains a URl of the referring site or application. For example, if someone clicked from a search result it might say <code>https://yahoo.com</code>.</p>

<p>The other way is using "Urchin Tracking Module" query strings. At the end of the URl they visit, they might append something like <code>?utm_source=alices-newsletter</code>.</p>

<p>Some sites, like Reddit, might use multiple subdomains - <code>old.reddit.com</code> or <code>out.reddit.com</code> - so some deduplication may be necessary.</p>

<h2 id="where-in-the-world-are-they"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#where-in-the-world-are-they">Where in the world are they?</a></h2>

<p>A user's IP address is <em>somewhat</em> accurate method of detecting their location. Yes, users could be proxying through a VPN or using a SIM card from a foreign country. But this isn't an exercise in precise tracking. Rough and ready is fine.</p>

<p>There are a variety of <a href="https://mailfud.org/geoip-legacy/">GeoIP Databases</a> which are updated semi-regularly. I'm only interested in the country of origin, I don't care about finer resolution than that.</p>

<p>Again, the aim isn't precise targetting. I'd just like to know that people in Sudan ever read my blog posts.</p>

<h2 id="what-else-could-we-use"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#what-else-could-we-use">What else could we use?</a></h2>

<p>It <em>might</em> be nice to know if someone is using a small-screen or large device. But my CSS is responsive, so I don't care.</p>

<p>Similarly, their Internet connection speed might be available. But, again, I try to optimise things so that isn't necessary to know.</p>

<p>Do I need to know if someone speaks Hungarian? No. There's nothing useful I can do with that information.</p>

<p>Could I extract their operating system, device, and browser from their User-Agent? I guess. Would I use the information that X% of my readers use Firefox on Linux? Doubtful!</p>

<h2 id="collect-the-information"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#collect-the-information">Collect the information</a></h2>

<p>There are two main methods of collecting these data.</p>

<p>First is a "no JavaScript" solution. This tells the browser to request an image which has a query string to send along the details of the page requested.</p>

<pre><code class="language-php">&lt;noscript&gt;
    &lt;img src="/tracking.php?ID=&lt;?php echo $postID ?&gt;" alt="" width=1 height=1 class=hidden&gt;
&lt;/noscript&gt;
</code></pre>

<p>The downside is that there's no way to capture referer information. If each page were dynamically generated, I could grab it from PHP's <code>$_SERVER</code> superglobal. But my website is heavily cached, so that isn't possible.</p>

<p>It <em>is</em> possible to use JavaScript to dynamically send the information for collection:</p>

<pre><code class="language-js">let formData = new FormData();
formData.append("HTTP_REFERER", document.referrer);
formData.append("ID",  &lt;?php echo $postID ?&gt;);

fetch("/tracking.php", {
    method: "POST",
    body: formData,
});
</code></pre>

<p>This approach has three distinct advantages.</p>

<ol>
<li>It works whether the user has JS enabled or not.</li>
<li>Repeated requests for the same page will usually reload the image from cache, so won't double-count.</li>
<li>It doesn't count hits from bots. They typically don't execute JavaScript or don't request images.</li>
</ol>

<h2 id="bot-detection"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#bot-detection">Bot Detection</a></h2>

<p>Not all traffic originates from humans. There are lots of bots which crawl the web. Some are useful - like search engines building up a map. Others are harmful - like AI agents aggressively scraping content to plagiarise.</p>

<p>There are <a href="https://www.humansecurity.com/learn/blog/crawlers-list-known-bots-guide/">lots of identifiable bots</a> out there - and more which obfuscate themselves. There are some, like <a href="https://github.com/GoogleChrome/lighthouse/pull/14384">Lighthouse</a> which cloak themselves.</p>

<p>I'm not trying to eliminate everything which <em>could</em> be a bot. I am trying for <em>reasonably</em> accurate. So I eliminate any User-Agent which contains:</p>

<p><code>"/bot|crawl|spider|seo|lighthouse|facebookexternalhit|preview|HeadlessChrome/i"</code></p>

<p>There are some <a href="https://github.com/fabiomb/is_bot">big lists of bots</a> you can use - but they don't seem to trigger my analytics because they aren't requesting the images or executing the JS.</p>

<h2 id="what-bits-of-the-site-to-measure"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#what-bits-of-the-site-to-measure">What bits of the site to measure?</a></h2>

<p>I only care about how many visitors my posts and pages get. I don't need to know if someone visited a tag page, or scrolled back to page 100 of posts from 2019. Those sorts of deep pages are usually only accessed by bots anyway.</p>

<p>I also don't want to count visits from me, myself, and I.</p>

<p>So the tracking is only inserted on single pages which are viewed by non-admins:</p>

<pre><code class="language-php">if ( is_singular() &amp;&amp; !current_user_can( "edit_posts" ) ) {
    …
}
</code></pre>

<h2 id="oddities"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#oddities">Oddities</a></h2>

<p>Sometimes, the URl requested will look something like: <code>https://shkspr-mobi.translate.goog</code> - that just means Google has translated it.</p>

<p>Sometimes, the referer will look something like: <code>android-app://com.google.android.gm/</code> - that just means they clicked from an Android app.</p>

<p>Sometimes, the URl requested will include a fragment or a query string - they can be ignored.</p>

<p>Sometimes, the <code>utm_</code> will contain all sorts of weird stuff. It isn't always possible to pull out exactly where it has come from.</p>

<p>Sometimes, the referer and <code>utm_</code> will disagree. Ah well, never mind.</p>

<p>Sometimes, RSS views are counted and sometimes not. Perhaps I should fix that?</p>

<p>Sometimes, users block trackers or use a text-only browser. That's fine, they can keep their secrets.</p>

<h2 id="saving-the-data"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#saving-the-data">Saving the data</a></h2>

<p>I started this by just shoving what I collected into a CSV.</p>

<pre><code class="language-php">//  Write the CSV.
$line = [date("c"), $ID, $UA, $referer, $domain, $country, $user];
//  Date-based filename.
$filename = "log-" . date("Y-m-d") . ".csv";
//  Append mode.
$handle = fopen( $filename, "a" );
fputcsv( $handle, $line );
fclose( $handle );
</code></pre>

<p>Nothing fancy. Something easily grepable with the ability to query it in more detail if I need.  At the number of hits that my site gets, it is less than 1MB per day.</p>

<p>I've since moved it into a single MySQL table. That might not be sustainable with hundreds of thousands of rows. But that's tomorrow's problem.</p>

<h2 id="accuracy"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#accuracy">Accuracy</a></h2>

<p>I've been running this for a couple of days - simultaneously with my other, more professional, stats plugin. It is within 5% accuracy. It appears to <em>slightly</em> exaggerate the number of visitors and undercount my page-views. That's good enough for my purposes and probably good for my ego!</p>

<h2 id="putting-it-all-together"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#putting-it-all-together">Putting it all together</a></h2>

<p>You can take a look at all the code <a href="https://gitlab.com/edent/blog-theme/">on my GitLab repo</a>.</p>

<h2 id="what-does-it-look-like"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#what-does-it-look-like">What does it look like?</a></h2>

<p>If you've made it this far, you can have a little pictorial treat! Aren't you lucky?</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/09/stats-view.webp" alt="Three tables. One showing referers with colourful favicons. Another countries with colourful emoji flags. One a list of pages and views." width="2450" height="1400" class="aligncenter size-full wp-image-63260">

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#whats-next">What's next?</a></h2>

<p>For now, a simple table structure is fine. I've shoved it in a basic database. Sure, I don't have any indexes or fancy stuff like that. But modern computers are pretty fast.</p>

<p>Eventually I'll need to create some new tables which will consolidate the data. Perhaps a table for individual posts, using date and country? Or maybe referer? I'll have to see.</p>

<p>I also need a way to get historic data into it. I've blog stats going back to 2009 which I am anxious not to lose.</p>

<p>And, yeah, I'll need a better front-end than manually running SQL queries.</p>

<p>Above all, I want to keep it simple enough that my puny mortal brain can understand it after several years of not touching anything. I want to build something which can run without constant maintenance.</p>

<p>Remember, this is only an exercise in self-learning, self-hosting, and self-respect.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:learn">
<p>I enjoy learning. If you're about to say "Why not just install…" then you've missed the point. I like understanding how things work, I get joy from discovering some new function, my brain feels happy when it is working on a problem. I don't want to just click install, hit next a few times, and fiddle with a few options. <a href="https://shkspr.mobi/blog/2020/12/build-dont-buy/">I've written more about my philosophy here</a>.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#fnref:learn" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:orisit">
<p>Or is it? There are 4 billion IPv4 addresses - although slightly fewer in actual use. Creating a rainbow table with 4 billion rows is possible if I was <em>just</em> using IP addresses. But there are an almost infinite variety of User Agent strings. It is probably possible to create a rainbow table of, for example, the 10 most popular UAs, concatenate them with every possible IP address, and then see which hashes to <code>65fef01fef257963</code>. But even then, what would that get an attacker? Knowing that the most popular model of iPhone is on a mobile network's IP range isn't exactly private information.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/#fnref:orisit" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63158&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Using Tempest Highlight with WordPress]]></title>
		<link>https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 26 Apr 2025 11:34:19 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=59866</guid>

					<description><![CDATA[I like to highlight bits of code on my blog. I was using GeSHi - but it has ceased to receive updates and the colours it uses aren&#039;t WCAG compliant.  After skimming through a few options, I found Tempest Highlight. It has nearly everything I want in a code highlighter:        PHP with no 3rd party dependencies.      Lots of common languages.      Modern, with regular updates.      Easy to use fun…]]></description>
										<content:encoded><![CDATA[<p>I like to highlight bits of code on my blog. I <em>was</em> using <a href="https://shkspr.mobi/blog/2025/04/a-small-php-update-to-geshi/">GeSHi</a> - but it has ceased to receive updates and the colours it uses aren't WCAG compliant.</p>

<p>After skimming through a few options, I found <a href="https://github.com/tempestphp/highlight">Tempest Highlight</a>. It has <em>nearly</em> everything I want in a code highlighter:</p>

<ul style="list-style-type: &quot;✅&quot;;">
    <li>&nbsp;PHP with no 3rd party dependencies.</li>
    <li>&nbsp;Lots of common languages.</li>
    <li>&nbsp;Modern, with regular updates.</li>
    <li>&nbsp;Easy to use functions.</li>
    <li>&nbsp;Range of difference style sheets.</li>
</ul>

<p>But, on the downside:</p>

<ul style="list-style-type: &quot;❌&quot;;">
    <li>&nbsp;No WordPress plugin.</li>
    <li>&nbsp;Not all languages supported.</li>
    <li>&nbsp;CSS embedded in HTML.</li>
</ul>

<p>I can live without some esoteric languages, but I don't really want to run <code>composer install</code> on my blog. I just want a quick WordPress plugin.  So, here's how I did it.</p>

<p></p><nav role="doc-toc"><menu><li><h2 id="table-of-contents"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#table-of-contents">Table of Contents</a></h2><menu><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#here-be-dragons">Here Be Dragons</a></li><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#the-art-of-loading-without-loading">The Art of Loading without Loading</a></li><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#testing">Testing</a></li><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#draw-the-rest-of-the-owl">Draw The Rest of the Owl</a></li><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#todo">ToDo</a></li><li><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#get-the-code">Get the code</a></li></menu></li></menu></nav><p></p>

<h2 id="here-be-dragons"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#here-be-dragons">Here Be Dragons</a></h2>

<p>This is a quick prototype. It has an audience of one; me. It may break in unexpected ways. Use at your own risk.</p>

<p>The file layout is relatively simple:</p>

<pre><code class="language-_">WordPress Plugins
├── Highlight_Plugin
│&nbsp;&nbsp; ├── src/
│&nbsp;&nbsp; ├── autoload.php
│&nbsp;&nbsp; ├── index.php
│&nbsp;&nbsp; └── base.css
</code></pre>

<p>The <code>src/</code> directory contains the <code>src/</code> directory from <a href="https://github.com/tempestphp/highlight">Tempest Highlight</a>.</p>

<h2 id="the-art-of-loading-without-loading"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#the-art-of-loading-without-loading">The Art of Loading without Loading</a></h2>

<p>Normally, to install a PHP package, the <code>composer</code> app creates an autoloader which will magically import everything you need into your project.  We can't do that here. Instead, we need to manually load the library.</p>

<p>Create a file in the plugin's directory called <code>autoload.php</code> - its job is to autoload everything in the <code>src/</code> directory.</p>

<pre><code class="language-php">&lt;?php
spl_autoload_register( function ( $class ) {
    //  Project-specific namespace prefix
    $prefix = "Tempest\\Highlight\\";

    //  Base directory for the namespace prefix
    $base_dir = __DIR__ . "/src/";

    //  Does the class use the namespace prefix?
    $len = strlen( $prefix );
    if ( strncmp( $prefix, $class, $len ) !== 0) {
        //  No, move to the next registered autoloader
        return;
    }

    //  Get the relative class name
    $relative_class = substr( $class, $len );

    //  Replace namespace separators with directory separators, append with .php
    $file = $base_dir . str_replace( "\\", "/", $relative_class ) . ".php";

    //  If the file exists, require it
    if ( file_exists( $file ) ) {
        require $file;
    }
});
</code></pre>

<p>I don't know if that's the <em>easiest</em> way to do it. But it works!</p>

<h2 id="testing"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#testing">Testing</a></h2>

<p>The <code>index.php</code> file can now be tested:</p>

<pre><code class="language-php">//  Load the Tempest Highlight library
require_once __DIR__ . "/autoload.php";

//  Set up the namespace
use Tempest\Highlight\Highlighter;

//  Define the theme.
$theme = new Tempest\Highlight\Themes\InlineTheme( __DIR__ . "/src/Themes/Css/light-plus.css");

//  Create the highlighter.
$highlighter = new Tempest\Highlight\Highlighter( $theme );

//  Print some formatted HTML
echo $highlighter-&gt;parse("&lt;em id='foo' class='bar'&gt;test&lt;/em&gt;", "html" );
</code></pre>

<p>All being well, that should produce this:</p>

<pre><code class="language-_">&amp;lt;&lt;span style="color: #0000ff;"&gt;em&lt;/span&gt; id='foo' class='bar'&amp;gt;test&amp;lt;/&lt;span style="color: #0000ff;"&gt;em&lt;/span&gt;&amp;gt;
</code></pre>

<p>That has the CSS embedded. Not ideal, but certainly good enough.  I picked "light-plus" because it was the only theme which seemed to meet at least WCAG AA when on a white background.</p>

<p>OK, so how do we go from printing out a scrap of HTML to extracting all the code snippets from a WordPress blog?</p>

<h2 id="draw-the-rest-of-the-owl"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#draw-the-rest-of-the-owl">Draw The Rest of the Owl</a></h2>

<p>In <em>theory</em> the code is relatively straightforward.</p>

<h3 id="find-code-snippets"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#find-code-snippets">Find code snippets</a></h3>

<p>My <a href="https://codeberg.org/edent/markdown-extra-unofficial/">Markdown plugin</a> transforms this:</p>

<pre><code class="language-_"> ```javascript
 var a = 2.0;
 ``` 
</code></pre>

<p>Into this:</p>

<pre><code class="language-html">&lt;pre&gt;&lt;code class="language-javascript"&gt;
var a = 2.0;
&lt;/code&gt;&lt;/pre&gt;
</code></pre>

<p>No need to use a regex, the new PHP 8.4 HTMLDocument gives us direct programmatic access to the HTML.</p>

<pre><code class="language-php">//  Load the content into PHP 8.4's HTML DOM.
$dom = Dom\HTMLDocument::createFromString( $content, LIBXML_NOERROR | LIBXML_HTML_NOIMPLIED, "UTF-8" );

//  Select the code snippets.
//  `&lt;pre&gt;&lt;code class="language-*"&gt;`
$codeSnippets = $dom-&gt;querySelectorAll( "pre&gt;code[class^=language-]" );
</code></pre>

<h3 id="replace-the-snippets"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#replace-the-snippets">Replace the snippets</a></h3>

<p>From the above, I have the language and code, so it can "easily" be replaced.</p>

<pre><code class="language-php">//  Iterate through each snippet.
foreach ( $codeSnippets as $code ) {
    //  Get the HTML from within the &lt;code&gt;.
    $originalCode = $code-&gt;textContent;
    //  Replace the contents of &lt;code&gt; with the highlighted HTML.
    $code-&gt;innerHTML = $highlighter-&gt;parse( $originalCode, $language )
}
</code></pre>

<p>Replacing the code in that node manipulates the original DOM.  Which means, after looping through all the snippets, I can return the altered HTML like so:</p>

<pre><code class="language-php">return $dom-&gt;saveHTML();
</code></pre>

<h3 id="and-then"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#and-then">And then…</a></h3>

<p>Obviously, there's a bit more too it than that. It ignores RSS feeds, it adds a base CSS style to the head, some SVGs get embedded, semantic metadata is included, and it all gets a bit tangled and complicated.</p>

<h2 id="todo"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#todo">ToDo</a></h2>

<p>A few things need to happen to make this even better.</p>

<ul>
<li>Encoded comments as well and posts.</li>
<li>Add new languages.</li>
<li>Don't in-line the CSS into the HTML, but add it as a separate stylesheet.</li>
</ul>

<p>But, for now, it is running on my blog and that's good enough for me!</p>

<h2 id="get-the-code"><a href="https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/#get-the-code">Get the code</a></h2>

<p>You can <a href="https://github.com/edent/highlight">play about with the WordPress plugin</a>. Bugs reports, pull requests, and suggestions all warmly welcomed.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=59866&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/04/using-tempest-highlight-with-wordpress/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Change the way dates are presented in WordPress's admin view]]></title>
		<link>https://shkspr.mobi/blog/2025/02/change-the-way-dates-are-presented-in-wordpresss-admin-view/</link>
					<comments>https://shkspr.mobi/blog/2025/02/change-the-way-dates-are-presented-in-wordpresss-admin-view/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 26 Feb 2025 12:34:21 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58427</guid>

					<description><![CDATA[WordPress does not respect an admin&#039;s preferred date format.  Here&#039;s how the admin list of posts looks to me:    I don&#039;t want it to look like that. I want it in RFC3339 format.  I know what you&#039;re thinking, just change the default date display - but that only seems to work in some areas of WordPress. It doesn&#039;t change the column-date format.  Here&#039;s what mine is set to:    So that doesn&#039;t work. …]]></description>
										<content:encoded><![CDATA[<p>WordPress does not respect an admin's preferred date format.</p>

<p>Here's how the admin list of posts looks to me:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/WP-Date-Wrong-fs8.png" alt="Column with the date format separated by slashes." width="420" height="674" class="aligncenter size-full wp-image-58437">

<p>I don't want it to look like that. I want it in RFC3339 format.</p>

<p>I know what you're thinking, <a href="https://wordpress.org/documentation/article/customize-date-and-time-format/">just change the default date display</a> - but that only seems to work in some areas of WordPress. It doesn't change the <code>column-date</code> format.  Here's what mine is set to:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/WP-date-format-fs8.png" alt="Settings screen showing date format set to dashes." width="940" height="414" class="aligncenter size-full wp-image-58432">

<p>So that doesn't work.</p>

<p>Instead, you need to use <a href="https://developer.wordpress.org/reference/hooks/post_date_column_time/">the slightly obscure <code>post_date_column_time</code> filter</a></p>

<p>Add this to your theme's <code>functions.php</code>:</p>

<pre><code class="language-php">//  Admin view - change date format
function rfc3339_post_date_time( $time, $post ) {
    //  Modify the default time format
    $rfc3339_time = date( "Y-m-d H:i", strtotime( $post-&gt;post_date ) );
    return $rfc3339_time;
}
add_filter( "post_date_column_time", "rfc3339_post_date_time", 10, 2 );
</code></pre>

<p>And, hey presto, your date column will look like this:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/WP-Date-Rigth-fs8.png" alt="Column with the date format separated by dashes." width="420" height="670" class="aligncenter size-full wp-image-58438"></p>

<p>Obviously, you can change that code to whichever date format you prefer.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58427&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/change-the-way-dates-are-presented-in-wordpresss-admin-view/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Graphing the connections between my blog posts]]></title>
		<link>https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/</link>
					<comments>https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 09 Jan 2025 12:34:56 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[graphs]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=55159</guid>

					<description><![CDATA[I love ripping off good ideas from other people&#039;s blogs.  I was reading Alvaro Graves-Fuenzalida&#039;s blog when I saw this nifty little force-directed graph:    When zoomed in, it shows the relation between posts and tags.    In this case, I can see that the posts about Small Gods and Pyramids both share the tags of Discworld, Fantasy, and Book Review. But only Small Gods has the tag of Religion. …]]></description>
										<content:encoded><![CDATA[<p>I love ripping off good ideas from other people's blogs.  I was reading <a href="https://stuff.graves.cl/posts/2024-03-05_20_41-book-review---small-gods-by-terry-pratchett.html">Alvaro Graves-Fuenzalida's blog</a> when I saw this nifty little force-directed graph:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/12/Graph-fs8.png" alt="A graph of interconnected nodes." width="800" height="600" class="aligncenter size-full wp-image-55160">

<p>When zoomed in, it shows the relation between posts and tags.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/12/Graph-detail-fs8.png" alt="Text labels on the nodes show that the two of the posts share a common tag." width="1600" height="1200" class="aligncenter size-full wp-image-55161">

<p>In this case, I can see that the posts about Small Gods and Pyramids both share the tags of Discworld, Fantasy, and Book Review. But only Small Gods has the tag of Religion.</p>

<p>Isn't that cool! It is a native feature of <a href="https://quartz.jzhao.xyz/features/graph-view">Quartz's GraphView</a>. How can I build something like that for my WordPress blog?</p>

<h2 id="aim"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#aim">Aim</a></h2>

<p>Create an interactive graph which shows the relationship between a post, its links, and their tags.</p>

<p>It will end up looking something like this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/12/fdg.png" alt="A force directed graph showing how four different posts link to each other and how their hashtags relate." width="1188" height="1088" class="aligncenter size-full wp-image-55169">

<p>You can <a href="https://gitlab.com/edent/blog-theme/-/blob/master/includes/graph.php">get the code</a> or follow along to see how it works.</p>

<p>This is a multi-stage process. Let's begin!</p>

<h2 id="what-we-need"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#what-we-need">What We Need</a></h2>

<p>When on a single Post, we need the following:</p>

<ul>
<li>The tags assigned to that Post.</li>
<li>Internal links back to that Post.</li>
<li>Internal links from that Post.</li>
<li>The tags assigned to links to and from that Post.</li>
</ul>

<h2 id="tags-assigned-to-that-post"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#tags-assigned-to-that-post">Tags assigned to that Post.</a></h2>

<p>This is pretty easy!  Using the <a href="https://developer.wordpress.org/reference/functions/get_the_tag_list/"><code>get_the_tag_list()</code> function</a> we can, unsurprisingly, get all the tags associated with a post.</p>

<pre><code class="language-php">$post_tags_text = get_the_tag_list( "", ",", $ID );
$post_tags_array = explode( "," , $post_tags_text );
</code></pre>

<p>That just gets the list of tag names. If we want the tag IDs as well, we need to use <a href="https://developer.wordpress.org/reference/functions/get_the_tags/">the <code>get_the_tags()</code> function</a>.</p>

<pre><code class="language-php">$post_tags = get_the_tags($ID);
$tags = array();
foreach($post_tags as $tag) {
    $tags[$tag-&gt;term_id] = $tag-&gt;name; 
}
</code></pre>

<h2 id="backlinks"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#backlinks">Backlinks</a></h2>

<p>Internal links back to the Post is slightly trickier. WordPress doesn't save relational information like that. Instead, we get the Post's URl and <a href="https://shkspr.mobi/blog/2023/10/displaying-internal-linkbacks-on-wordpress/">search for that in the database</a>. Then we get the post IDs of all the posts which contain that string.</p>

<pre><code class="language-php">//  Get all the posts which link to this one, oldest first
$the_query = new WP_Query(
    array(
        's' =&gt; $search_url,
        'post_type' =&gt; 'post',
        "posts_per_page" =&gt; "-1",
        "order" =&gt; "ASC"
    )
);

//  Nothing to do if there are no inbound links
if ( !$the_query-&gt;have_posts() ) {
    return;
}
</code></pre>

<h2 id="backlinks-tags"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#backlinks-tags">Backlinks' Tags</a></h2>

<p>Once we have an array of posts which link back here, we can get their tags as above:</p>

<pre><code class="language-php">//  Loop through the posts
while ( $the_query-&gt;have_posts() ) {
    //  Set it up
    $the_query-&gt;the_post();
    $id                  = get_the_ID();
    $title               = esc_html( get_the_title() );
    $url                 = get_the_permalink();
    $backlink_tags_text  = get_the_tag_list( "", ",", $ID );
    $backlink_tags_array = explode( "," , $backlink_tags_text );
}
</code></pre>

<h2 id="links-from-the-post"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#links-from-the-post">Links from the Post</a></h2>

<p>Again, WordPress's lack of relational links is a weakness. In order to get internal links, we need to:</p>

<ol>
<li>Render the HTML using all the filters</li>
<li>Search for all <code>&lt;a href="…"&gt;</code></li>
<li>Extract the ones which start with the blog's domain</li>
<li>Get those posts' IDs.</li>
</ol>

<p>Rendering the content into HTML is done with:</p>

<pre><code class="language-php">$content = apply_filters( "the_content", get_the_content( null, false, $ID ) );
</code></pre>

<p>Searching for links is slightly more complex. The easiest way is to load the HTML into a DOMDocument, then extract all the anchors. All my blog posts start <code>/blog/YYYY</code> so I can avoid selecting links to tags, uploaded files, or other things. Your blog may be different.</p>

<pre><code class="language-php">$dom = new DOMDocument();
libxml_use_internal_errors( true ); //  Suppress warnings from malformed HTML
$dom-&gt;loadHTML( $content );
libxml_clear_errors();

$links = [];
foreach ( $dom-&gt;getElementsByTagName( "a" ) as $anchor ) {
    $href = $anchor-&gt;getAttribute( "href" );
    if (preg_match('/^https:\/\/shkspr\.mobi\/blog\/\d{4}$/', $href)) {
        $links[] = $href;
    }
}
</code></pre>

<p>The ID of each post can be found with <a href="https://developer.wordpress.org/reference/functions/url_to_postid/">the <code>url_to_postid()</code> function</a>. That means we can re-use the earlier code to see what tags those posts have.</p>

<h2 id="building-a-graph"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#building-a-graph">Building a graph</a></h2>

<p>OK, so we have all our constituent parts. Let's build a graph!</p>

<p>Graphs consist of nodes (posts and tags) and edges (links between them). The exact format of the graph is going to depend on the graph library we use.</p>

<p>I've decided to use <a href="https://github.com/d3/d3-force?tab=readme-ov-file">D3.js's Force Graph</a> as it is relatively simple and produces a reasonably good looking interactive SVG.</p>

<p>Imagine there are two blog posts and two hashtags.</p>

<pre><code class="language-js">const nodes = [
    { id: 1, label: "Blog Post 1",    url: "https://example.com/post/1", group: "post" },
    { id: 2, label: "Blog Post 2",    url: "https://example.com/post/2", group: "post" },
    { id: 3, label: "hashtag",        url: "https://example.com/tag/3",  group: "tag"  },
    { id: 4, label: "anotherHashtag", url: "https://example.com/tag/4",  group: "tag"  },
];
</code></pre>

<ul>
<li>Blog Post 1 links to Blog Post 2.</li>
<li>Blog Post 1 has a #hashtag.</li>
<li>Both 1 &amp; 2 share #anotherHashtag.</li>
</ul>

<pre><code class="language-js">const links = [
    { source: 1, target: 2 },
    { source: 3, target: 1 },
    { source: 4, target: 1 },
    { source: 4, target: 2 },
];
</code></pre>

<p>Here's how to create a list of nodes and their links.  You will need to edit it for your own blog's peculiarities.</p>

<pre><code class="language-php">&lt;?php 
// Load WordPress environment
require_once( "wp-load.php" );

//  Set up arrays for nodes and links
$nodes = array();
$links = array();

//  ID of the Post
$main_post_id = 12345;

//  Get the Post's details
$main_post_url   = get_permalink( $main_post_id );
$main_post_title = get_the_title( $main_post_id );

//  Function to add new nodes
function add_item_to_nodes( &amp;$nodes, $id, $label, $url, $group ) {
    $nodes[] = [ 
        "id"    =&gt; $id, 
        "label" =&gt; $label, 
        "url"   =&gt; $url, 
        "group" =&gt; $group
    ];

}

//  Function to add new relationships
function add_relationship( &amp;$links, $source, $target ) {
    $links[] = [
        "source" =&gt; $source,
        "target" =&gt; $target
    ];
}

//  Add Post to the nodes
add_item_to_nodes( $nodes, $main_post_id, $main_post_title, $main_post_url, "post" );

//  Get the tags of the Post
$main_post_tags = get_the_tags( $main_post_id );

//  Add the tags as nodes, and create links to main Post
foreach( $main_post_tags as $tag ) {
    $id   = $tag-&gt;term_id;
    $name = $tag-&gt;name;

    //  Add the node
    add_item_to_nodes( $nodes, $id, $name, "https://shkspr.mobi/blog/tag/" . $name, "tag" );
    //  Add the relationship
    add_relationship( $links, $id, $main_post_id );
}

//  Get all the posts which link to this one, oldest first
$the_query = new WP_Query(
    array(
        's'              =&gt; $main_post_url,
        'post_type'      =&gt; 'post',
        "posts_per_page" =&gt; "-1",
        "order"          =&gt; "ASC"
    )
);

//  Nothing to do if there are no inbound links
if ( $the_query-&gt;have_posts() ) {
    //  Loop through the posts
    while ( $the_query-&gt;have_posts() ) {
        //  Set up the query
        $the_query-&gt;the_post();
        $post_id = get_the_ID();
        $title = esc_html( get_the_title() );
        $url   = get_the_permalink();

        //  Add the node
        add_item_to_nodes( $nodes, $post_id, $title, $url, "post" );
        //  Add the relationship
        add_relationship( $links, $post_id, $main_post_id );

        //  Get the tags of the Post
        $post_tags = get_the_tags( $post_id );

        //  Add the tags as nodes, and create links to main Post
        foreach($post_tags as $tag) {

            $id   = $tag-&gt;term_id;
            $name = $tag-&gt;name;

            //  Add the node
            add_item_to_nodes( $nodes, $id, $name, "https://shkspr.mobi/blog/tag/" . $name, "tag" );
            //  Add the relationship
            add_relationship( $links, $id, $post_id );
        }

    }
}

//  Get all the internal links from this post
//  Render the post as HTML
$content = apply_filters( "the_content", get_the_content( null, false, $ID ) );

//  Load it into HTML
$dom = new DOMDocument();
libxml_use_internal_errors( true );
$dom-&gt;loadHTML( $content );
libxml_clear_errors();

//  Get any &lt;a href="…" which starts with https://shkspr.mobi/blog/
$internal_links = [];
foreach ( $dom-&gt;getElementsByTagName( "a" ) as $anchor ) {
    $href = $anchor-&gt;getAttribute( "href" );
    if (preg_match('/^https:\/\/shkspr\.mobi\/blog\/\d{4}$/', $href)) {
        $internal_links[] = $href;
    }
}

//  Loop through the internal links, get their hashtags
foreach ( $internal_links as $url ) {
    $post_id = url_to_postid( $url );
    //  Get the Post's details
    $post_title = get_the_title( $id );

    //  Add the node
    add_item_to_nodes( $nodes, $post_id, $post_title, $url, "post" );
    //  Add the relationship
    add_relationship($links, $main_post_id, $post_id );

    //  Get the tags of the Post
    $post_tags = get_the_tags( $post_id );

    //  Add the tags as nodes, and create links to main Post
    foreach( $post_tags as $tag ) {
        $id   = $tag-&gt;term_id;
        $name = $tag-&gt;name;

        //  Add the node
        add_item_to_nodes( $nodes, $id, $name, "https://shkspr.mobi/blog/tag/" . $name, "tag" );
        //  Add the relationship
        add_relationship( $links, $id, $post_id );
    }
}

//  Deduplicate the nodes and links
$nodes_unique = array_unique( $nodes, SORT_REGULAR );
$links_unique = array_unique( $links, SORT_REGULAR );

//  Put them in the keyless format that D3 expects
$nodes_output = array();
$links_output = array();

foreach ( $nodes_unique as $node ) {
    $nodes_output[] = $node;
}

foreach ( $links_unique as $link ) {
    $links_output[] = $link;
}

//  Return the JSON
echo json_encode( $nodes_output, JSON_PRETTY_PRINT );
echo "\n";
echo json_encode( $links_output, JSON_PRETTY_PRINT );
</code></pre>

<h2 id="creating-a-force-directed-svg"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#creating-a-force-directed-svg">Creating a Force Directed SVG</a></h2>

<p>Once the data are spat out, you can include them in a web-page. Here's a basic example:</p>

<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8"&gt;
        &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
        &lt;title&gt;Force Directed Graph&lt;/title&gt;
        &lt;script src="https://d3js.org/d3.v7.min.js"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;svg width="800" height="600"&gt;
            &lt;defs&gt;
                &lt;marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto" fill="#999"&gt;
                &lt;path d="M0,0 L10,3.5 L0,7 Z"&gt;&lt;/path&gt;
                &lt;/marker&gt;
            &lt;/defs&gt;
        &lt;/svg&gt;
        &lt;script&gt;
</code></pre>

<pre><code class="language-js">            const nodes = [];
            const links = [];

            const width  = 800;
            const height = 600;

            const svg = d3.select("svg")
                .attr( "width",  width  )
                .attr( "height", height );

            const simulation = d3.forceSimulation( nodes )
                .force( "link",   d3.forceLink( links ).id( d =&gt; d.id ).distance( 100 ) )
                .force( "charge", d3.forceManyBody().strength( -300 ) )
                .force( "center", d3.forceCenter( width / 2, height / 2 ) );

            //  Run simulation with simple animation
            simulation.on("tick", () =&gt; {
                link
                    .attr("x1", d =&gt; d.source.x)
                    .attr("y1", d =&gt; d.source.y)
                    .attr("x2", d =&gt; d.target.x)
                    .attr("y2", d =&gt; d.target.y);   node
                    .attr("transform", d =&gt; `translate(${d.x},${d.y})`);
            });

            // Draw links
            const link = svg.selectAll( ".link" )
                .data(links)
                .enter().append("line")
                .attr( "stroke", "#999" )
                .attr( "stroke-width", 2 )
                .attr( "x1", d =&gt; d.source.x )
                .attr( "y1", d =&gt; d.source.y )
                .attr( "x2", d =&gt; d.target.x )
                .attr( "y2", d =&gt; d.target.y )
                .attr( "marker-end", "url(#arrowhead)" );

            //  Draw nodes
            const node = svg.selectAll( ".node" )
                .data( nodes )
                .enter().append( "g" )
                .attr( "class", "node" )
                .attr( "transform", d =&gt; `translate(${d.x},${d.y})` )
                .call(d3.drag() //  Make nodes draggable
                    .on( "start", dragStarted )
                    .on( "drag",  dragged )
                    .on( "end",   dragEnded ) 
                );

            //  Add hyperlink
            node.append("a")
            .attr( "xlink:href", d =&gt; d.url ) //    Link to the node's URL
            .attr( "target", "_blank" ) //  Open in a new tab
            .each(function (d) {
                const a = d3.select(this);
                //  Different shapes for posts and tags
                if ( d.group === "post" ) {
                    a.append("circle")
                        .attr("r", 10)
                        .attr("fill", "blue");
                } else if ( d.group === "tag" ) {
                    //  White background rectangle
                    a.append("rect")
                            .attr("width", 20)
                            .attr("height", 20)
                            .attr("x", -10)
                            .attr("y", -10)
                            .attr("fill", "white"); 
                    // Red octothorpe
                    a.append("path")
                            .attr("d", "M-10,-5 H10 M-10,5 H10 M-5,-10 V10 M5,-10 V10") 
                            .attr("stroke", "red")
                            .attr("stroke-width", 2)
                            .attr("fill", "none");
                }
                //  Text label
                a.append( "text")
                    .attr( "dy", 4 )
                    .attr( "x", d =&gt; ( d.group === "post" ? 12 : 14 ) )
                    .attr( "fill", "black" )
                    .style("font-size", "12px" )
                    .text( d.label );
            });

            //  Standard helper functions to make nodes draggable
            function dragStarted( event, d ) {
                if ( !event.active ) simulation.alphaTarget(0.3).restart();
                d.fx = d.x;
                d.fy = d.y;
            }
            function dragged( event, d ) {
                d.fx = event.x;
                d.fy = event.y;
            }
            function dragEnded( event, d ) {
                if (!event.active) simulation.alphaTarget(0);
                d.fx = null;
                d.fy = null;
            }
</code></pre>

<pre><code class="language-html">        &lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>

<h2 id="next-steps"><a href="https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/#next-steps">Next Steps</a></h2>

<p>It needs a bit of cleaning up if I want to turn it into a WordPress plugin. It might be nice to make it a static SVG rather than relying on JavaScript. And the general æsthetic needs a bit of work.</p>

<p>Perhaps I could make it 3D like my <a href="https://shkspr.mobi/blog/2023/04/msc-dissertation-exploring-the-visualisation-of-hierarchical-cybersecurity-data-within-the-metaverse/">MSc Dissertation</a>?</p>

<p>But I'm pretty happy with that for an afternoon hack!</p>

<p>You can <a href="https://gitlab.com/edent/blog-theme/-/blob/master/includes/graph.php">get the code</a> if you want to play.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=55159&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/01/graphing-the-connections-between-my-blog-posts/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Order WordPress Posts by Most Comments]]></title>
		<link>https://shkspr.mobi/blog/2024/12/order-wordpress-posts-by-most-comments/</link>
					<comments>https://shkspr.mobi/blog/2024/12/order-wordpress-posts-by-most-comments/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 12 Dec 2024 12:34:42 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=54404</guid>

					<description><![CDATA[I take great delight in seeing people reply to my blog posts.  I use WebMentions to collect replies from social media and other sites. But which of my posts has the most comments? Here&#039;s a snipped to stick in your functions.php file. It allows you to add ?comment-order to any WordPress URl and have the posts with the most comments on top.  //  Add ordering by comments add_action( &#039;pre_get_posts&#039;, …]]></description>
										<content:encoded><![CDATA[<p>I take great delight in seeing people reply to my blog posts.  I use WebMentions to collect replies from social media and other sites. But which of my posts has the most comments? Here's a snipped to stick in your <code>functions.php</code> file. It allows you to add <code>?comment-order</code> to any WordPress URl and have the posts with the most comments on top.</p>

<pre><code class="language-php">//  Add ordering by comments
add_action( 'pre_get_posts', 'pre_get_posts_by_comments' );
function pre_get_posts_by_comments( $query ) {
    //  Do nothing if the post_status parameter in the URL is not "comment-order"
    if ( ! isset( $_GET['comment-order'] ) ) {
        return;
    }

    $query-&gt;set( "orderby", "comment_count" );  //  Default: date
    $query-&gt;set( "order", "DESC" ); //  Biggest first
}
</code></pre>

<p>This makes use of <a href="https://developer.wordpress.org/reference/hooks/pre_get_posts/">the <code>pre_get_posts</code> hook</a> to rewrite the posts query. That means it works on most WordPress pages.</p>

<p>For example:</p>

<ul>
<li>My homepage <a href="https://shkspr.mobi/blog/?comment-order">https://shkspr.mobi/blog/?comment-order</a></li>
<li>Posts with a specific tag <a href="https://shkspr.mobi/blog/tag/blockchain/?comment-order">https://shkspr.mobi/blog/tag/blockchain/?comment-order</a></li>
<li>Dates <a href="https://shkspr.mobi/blog/2012/?comment-order">https://shkspr.mobi/blog/2012/?comment-order</a></li>
</ul>

<p>Did you find this post useful? Please leave a comment here!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=54404&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/12/order-wordpress-posts-by-most-comments/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Is WordPress.org GDPR compliant?]]></title>
		<link>https://shkspr.mobi/blog/2024/12/is-wordpress-org-gdpr-compliant/</link>
					<comments>https://shkspr.mobi/blog/2024/12/is-wordpress-org-gdpr-compliant/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 11 Dec 2024 12:34:25 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpdrama]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53689</guid>

					<description><![CDATA[A few weeks ago, I got a chance to speak truth to power. I used my WordPress.org account to sign in to the official WordPress.org Slack where the various WordPress dramas were being discussed.  After a brief chat about the latest shenanigans, I publicly replied to the CEO:    Here&#039;s a link to the full exchange  There was no reply forthcoming - although, as you can see, my message gathered a fair…]]></description>
										<content:encoded><![CDATA[<p>A few weeks ago, I got a chance to speak truth to power. I used my WordPress.org account to sign in to the <a href="https://make.wordpress.org/chat/">official WordPress.org Slack</a> where the various <a href="https://mullenweg.wtf/">WordPress dramas</a> were being discussed.</p>

<p>After a brief chat about the latest shenanigans, I publicly replied to the CEO:</p>

<p><a href="https://wordpress.slack.com/archives/C02QB8GMM/p1728563007042769?thread_ts=1728463928.352389&amp;cid=C02QB8GMM"><img src="https://shkspr.mobi/blog/wp-content/uploads/2024/12/Making-WordPress-Slack.webp" alt="Matt - I've never seen anyone spread so much FUD about their own project before. I started out as sympathetic to your cause against WP Engine. But your behaviour has driven me - and many other good people - away.  I want to be explicitly clear: I am in no position to judge the merits of your lawsuit, but I am in a position to judge your behaviour.  I cannot fathom why you are trying to turn your own community against you.  Please - reconsider your approach." width="1820" height="978" class="aligncenter size-full wp-image-54433"></a></p>

<p>Here's <a href="https://wordpress.slack.com/archives/C02QB8GMM/p1728563007042769?thread_ts=1728463928.352389&amp;cid=C02QB8GMM">a link to the full exchange</a></p>

<p>There was no reply forthcoming - although, as you can see, my message gathered a fair few positive reactions. <a href="https://mastodon.social/@Edent/113283116807769292">As was inevitable</a>, the next morning I found myself locked out of the Slack. I had been permabanned.</p>

<p>Then things got <em>weird</em>.</p>

<p>Someone claiming to be an employee of Automattic sent me a message saying that Matt had personally told people to ban me. I didn't know if they were telling the truth, but the GDPR gives me the right to see the data a company holds about me.  That includes <em>messages</em> about me stored on their internal systems.</p>

<p>The <a href="https://wordpress.org/about/privacy/">WordPress.org Privacy Policy</a> gave me an email address for their Data Protection Officer (DPO). So I sent a friendly(ish) message. After a little back-and-forth to clarify which data I wanted, I received this truly bizarre reply.</p>

<blockquote><p>We are in receipt of your request, which you claim is justified by GDPR. Accordingly, we are processing your request pursuant to section 15(3) of GDPR, which requires us to provide personal information about the person that we are processing.
You refer to messages sent about you on internal systems. To the extent those are outside the scope of GDPR, they are not covered by your request.</p></blockquote>

<p>This betrays a fundamental misunderstanding of GDPR. There is not, as far as I know, an exemption for records held on internal systems.  There are <a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/exemptions/a-guide-to-the-data-protection-exemptions/">a list of GDPR exemptions</a> - but they mostly relate to things like the detection of crime, academic and journalistic exemptions, health and social work data, etc.</p>

<p>Of course, there is an <a href="https://www.legislation.gov.uk/ukpga/2018/12/schedule/2/paragraph/20/enacted">exemption for the purposes of self-incrimination</a>. Perhaps that's what they're relying upon?</p>

<p>I replied with a (not so-friendly) email pointing out that I was entitled to a copy of any messages <em>because</em> they contain my personal data. I also pointed out that my request was neither manifestly unfounded nor manifestly excessive (another common get-out clause).</p>

<p>A week later, they replied:</p>

<blockquote><p>I’ve followed up looking for any related records, and can confirm no records which use your likeness exist, other than the following:
<code>edent was deactivated by &lt;&lt;REDACTEDUSER&gt;&gt;</code>
No records exist where this was discussed beforehand.</p></blockquote>

<p>I take this to mean that either Matt personally swung the ban-hammer, without discussing it with anyone else, or that a flunky wanted to protect their master's ego and took unilateral action.</p>

<p>They only provided me with messages from Slack that I had sent. They didn't provide any of the messages that mentioned me.</p>

<p>I pushed for further clarification - but their answer baffled me:</p>

<blockquote><p>The Slack instance you are asking about is a communication tool used by the WordPress volunteer community to coordinate on the project to build and maintain the open source WordPress software. <strong>There is no business or data controller that owns or manages this Slack.</strong> If one or more of the volunteers had a private discussion about you in this Slack you would need to direct your request to those individuals and they would need to decide themselves how to handle your request.</p></blockquote>

<p>(Emphasis added.)</p>

<p>This, to me, implies that they are not following <a href="https://slack.com/intl/en-gb/terms-of-service/user">Slack's term's and conditions</a> which explicitly say the owner of the Slack has to comply with data requests.</p>

<blockquote><p>As between [Slack] and the customer, you agree that it is solely the customer’s responsibility to […] respond to and resolve any dispute with you and any authorised user relating to or based on customer data</p></blockquote>

<p>Is this Slack <em>really</em> owned by volunteers? According to <a href="https://wordpress.slack.com/account/workspace-settings#admins">https://wordpress.slack.com/account/workspace-settings#admins</a> - the <em>primary</em> owner is WordPress.org itself. Although there are several other users listed as owners, including Matt himself.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/12/WordPress-Slack-Owners-fs8.png" alt="List of WordPress's Slack's owners." width="1024" height="1391" class="aligncenter size-full wp-image-54382">

<p>I specifically asked WordPress.org for details of their GDPR registration. Their reply is hilarious:</p>

<blockquote><p>WordPress.org is privately owned by a person, not by a registered or covered entity.</p>

<p>While the email address says “Data Protection Officer” this is merely to make it easy for Europeans to find and contact the privacy volunteers who, of course, want to do their best to assist persons with privacy related questions and requests. This does not indicate that WordPress.org is a GDPR covered website or owned by any entity which is subject to the GDPR.</p></blockquote>

<p>So now we're at an impasse. I have no way of knowing if the anonymous tip-off I received was genuine and I can't prove if WordPress are concealing messages to me. I think it is fair to say that <a href="https://wpandlegalstuff.com/the-not-affiliated-checkbox-and-the-gdpr/">other people feel that WordPress.org doesn't really understand the GDPR</a> - so we can add this example to the list.</p>

<p>To sum up:</p>

<ul>
<li><a href="https://www.theverge.com/2024/10/4/24262232/matt-mullenweg-wordpress-org-wp-engine">WordPress.org is personally owned by Matt Mullenweg</a></li>
<li>The website processes millions of users' data, yet has no GDPR policy.</li>
<li>Volunteers are apparently cosplaying as Data Protection Officers, without any real knowledge of how GDPR works.</li>
<li>An <a href="https://make.wordpress.org/chat/">official WordPress.org Slack</a> is run by WordPress.org with Matt &amp; others as admins.</li>
<li>This Slack processes the data of over 50,000 users <em>without</em> any GDPR compliance.</li>
</ul>

<p>In my opinion, this is no way to run a major piece of web infrastructure.  The community deserves better.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53689&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/12/is-wordpress-org-gdpr-compliant/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Change WordPress Fragment Links in RSS Feeds to be Permalinks]]></title>
		<link>https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/</link>
					<comments>https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 06 Dec 2024 12:34:14 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=54080</guid>

					<description><![CDATA[Here&#039;s a knotty problem. Lots of my posts use URl Fragments. Those are links which start with #. They allow me to write:  &#60;a href=&#34;#where-is-this-a-problem&#62;Jump to heading&#60;/a&#62;   So when someone clicks on a link, they go straight to the relevant section.  For example, they might want to skip straight to how to fix it.  Isn&#039;t that clever?  Where is this a problem?  This works great when someone is…]]></description>
										<content:encoded><![CDATA[<p>Here's a knotty problem. Lots of my posts use <a href="https://developer.mozilla.org/en-US/docs/Web/URI/Fragment">URl Fragments</a>. Those are links which start with <code>#</code>. They allow me to write:</p>

<pre><code class="language-html">&lt;a href="https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#where-is-this-a-problem&gt;Jump%20to%20heading&lt;/a&gt;/code/prepSo%20when%20someone%20clicks%20on%20a%20link,%20they%20a%20href="#where-is-this-a-problem">go straight to the relevant section</a>.  For example, they might want to skip straight to <a href="https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#how-to-fix-it">how to fix it</a>.</p>

<p>Isn't that clever?</p>

<h2 id="where-is-this-a-problem"><a href="https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#where-is-this-a-problem">Where is this a problem?</a></h2>

<p>This works great when someone is on my website. They're on the page, and a fragment links straight to the correct section of that page.</p>

<p>But some people view this blog in RSS &amp; Atom feeds - and those feeds also power my newsletter.</p>

<p>When those people see a fragment, it is devoid of its original context. So they end up going to some random location, or my homepage.</p>

<h2 id="how-to-fix-it"><a href="https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#how-to-fix-it">How to fix it?</a></h2>

<p>Stick this into your WordPress theme's <code>functions.php</code> file:</p>

<pre><code class="language-php">//  In the RSS feed, change #whatever to &lt;permalink&gt;#whatever
function rewrite_fragment_links_in_rss($content) {
    global $post;

    //  Ensure this is a feed
    if ( is_feed() &amp;&amp; $post instanceof WP_Post ) {
        //  Get the permalink
        $base_url = get_permalink( $post );

        //  Regex to get href="https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/#%20%20%20%20%20%20%20%20$content%20=%20preg_replace_callback(%20%20%20%20%20%20%20%20%20%20%20%20"/href=["\']#([^"\']+)["\']/',
            function ( $matches ) use ( $base_url ) {
                return 'href="' . esc_url( $base_url . '#' . $matches[1] ) . '"';
            },
            $content
        );
    }

    return $content;
}

//  Hook into feed filters for both excerpts and full content
add_filter( "the_excerpt_rss",  "rewrite_fragment_links_in_rss" );
add_filter( "the_content_feed", "rewrite_fragment_links_in_rss" );
</code></pre>

<p>That listens out for the RSS feed being generated and replaces <code>#whatever</code> with <code>https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks#whatever</code></p>

<p>Nifty!</p>

<p>Hopefully, if you click on the links in my emails and feeds, it should take you to the right place now.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=54080&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/12/change-wordpress-fragment-links-in-rss-feeds-to-be-permalinks/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Using phpList for a blog's newsletter]]></title>
		<link>https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/</link>
					<comments>https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 31 Oct 2024 12:34:36 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[newsletter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53583</guid>

					<description><![CDATA[Some people like to receive this blog via email. I previously used JetPack to send out subscriber messages - but it became increasingly clear that Automattic isn&#039;t a good steward of such things.  I couldn&#039;t find any services which would let me send a few thousand subscribers a few emails per week, at zero cost.  So, redecentralise!  I installed phpList which is an open source email campaign tool. …]]></description>
										<content:encoded><![CDATA[<p>Some people like to receive this blog via email. I previously used JetPack to send out subscriber messages - but it became increasingly clear that Automattic isn't a good steward of such things.  I couldn't find any services which would let me send a few thousand subscribers a few emails per week, at zero cost.</p>

<p>So, redecentralise!</p>

<p>I installed <a href="https://www.phplist.org/">phpList</a> which is an open source email campaign tool.  My webhost - <a href="https://krystal.io/">Krystal</a> - had a one-click install option. But, phpList isn't quite one-click for sending out a regular blog newsletter.  <a href="https://discuss.phplist.org/t/daily-rss-problems-there-are-no-feed-items-that-will-be-included-in-the-first-campaign/9835/">I found the set-up to be quite confusing</a>, so here are the steps I took to turn an RSS feed into an Email Newsletter for free.</p>

<h2 id="install-the-plugins"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#install-the-plugins">Install the plugins</a></h2>

<ol>
<li>Navigate to Config → Manage plugins</li>
<li>Enable "CommonPlugin"</li>
<li>Add the <a href="https://resources.phplist.com/plugin/rssfeed">RSS Feed Plugin</a> using the Plugin package URL <code>https://github.com/bramley/phplist-plugin-rssfeed/archive/master.zip</code></li>
</ol>

<h2 id="configure-the-rss-feed-plugin"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#configure-the-rss-feed-plugin">Configure the RSS Feed Plugin</a></h2>

<ol>
<li>Navigate to Config → Settings</li>
<li>Scroll down to the RSS Settings</li>
<li>Set both Minimum <em>and</em> Maximum number of items to 1<br><img src="https://shkspr.mobi/blog/wp-content/uploads/2024/10/rsssettings-fs8.png" alt="RSS Settings Screen." width="888" height="450" class="aligncenter size-full wp-image-53584"><br>That will ensure you only send the latest RSS item as your newsletter.</li>
<li>Set "Use the item summary content (the description or summary element) instead of the content element" to "No". This will allow the full text of the RSS item to be sent.</li>
</ol>

<h2 id="edit-config-php"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#edit-config-php">Edit <code>config.php</code></a></h2>

<p>For some reason, you need to manually edit this file in a text editor, rather than a GUI.</p>

<ol>
<li>Set <code>define('USE_REPETITION', 1);</code> - this allows the newsletter to be sent whenever there is a new RSS item.</li>
<li>Set <code>define('CLICKTRACK', 0);</code> - this removes tracking links from your emails. I don't care who opens my emails or what they click on.</li>
</ol>

<h2 id="add-the-campaign"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#add-the-campaign">Add The Campaign</a></h2>

<ol>
<li>Go to  Campaigns → Send a campaign.</li>
<li>Start a new campaign.</li>
</ol>

<h3 id="tab-1"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-1">Tab 1</a></h3>

<ol>
<li>Campaign subject should be <code>[RSSITEM:TITLE]</code> - that will make the subject line the same as your <strong>post</strong>'s title</li>
<li>Compose message should be <code>[RSS]</code> - that will ensure the contents come from your RSS feed.</li>
</ol>

<h3 id="tab-2"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-2">Tab 2</a></h3>

<ol>
<li>Add your RSS feed's URl</li>
<li>Order items "Newest" first - to get the most recent item.</li>
<li>Add a custom HTML template. I used one from <a href="https://emailframe.work/">https://emailframe.work/</a></li>
</ol>

<pre><code class="language-html">&lt;div style="margin:0; padding:0; background-color:#F2F2F2;"&gt;
  &lt;h1&gt;&lt;a href="[URL]"&gt;[TITLE]&lt;/a&gt;&lt;/h1&gt;
  &lt;table width="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#F2F2F2"&gt;
      &lt;tr&gt;
          &lt;td valign="top"&gt;
              [CONTENT]
          &lt;/td&gt;
      &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
</code></pre>

<h3 id="tab-3"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-3">Tab 3</a></h3>

<ol>
<li>Send as HTML</li>
</ol>

<h3 id="tab-4"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-4">Tab 4</a></h3>

<ol>
<li>"Stop sending after" - choose the furthest date in the future possible.</li>
<li>"Repeat campaign every" - I chose "hour". That should check the RSS feed each hour.</li>
</ol>

<h3 id="tab-5"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-5">Tab 5</a></h3>

<ol>
<li>"Lists" - pick the email list you want to send from.</li>
</ol>

<h3 id="tab-6"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#tab-6">Tab 6</a></h3>

<ol>
<li>You should be finished! It will tell you if there are any errors.</li>
<li>Place the campaign in the queue for processing.</li>
</ol>

<h2 id="wordpress-sign-up-form"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#wordpress-sign-up-form">WordPress Sign Up Form</a></h2>

<p>You can either redirect users to your phpList subscription page, or put a form directly on your site.</p>

<pre><code class="language-html">&lt;form method="post" action="/YourSubscribePage/?p=subscribe&amp;id=1" name="subscribeform"&gt;
    &lt;label for="email"&gt;Email address:&lt;/label&gt;
    &lt;input type="email" name="email" required="required" placeholder="" size="40" id="email"&gt;
    &lt;input type="hidden" name="htmlemail" value="1"&gt;
    &lt;input type="hidden" name="list[2]" value="signup"&gt;
    &lt;input type="hidden" name="listname[2]" value="newsletter"&gt;
    &lt;div style="display:none"&gt;
        &lt;input type="text" name="VerificationCodeX" value="" size="20"&gt;
    &lt;/div&gt;
    &lt;input type="submit" name="subscribe" value="Subscribe"&gt;
&lt;/form&gt;
</code></pre>

<p>Adjust the hidden parameters based on your list.</p>

<p>If in doubt, go to Config →  Subscribe pages, and generate a new subscribe page. Then copy the form from that.</p>

<h2 id="cron-jobs"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#cron-jobs">Cron Jobs</a></h2>

<p>You need two cron jobs set up.</p>

<h3 id="update-the-rss-feed"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#update-the-rss-feed">Update the RSS feed</a></h3>

<p>I run this every hour:</p>

<p><code>/usr/bin/php /path/to/YourSubscribePage/admin/index.php -p get -m RssFeedPlugin -c /path/to/YourSubscribePage/config/config.php</code></p>

<h3 id="process-the-queue"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#process-the-queue">Process the Queue</a></h3>

<p>I run this a few minutes after the RSS feed is updated</p>

<p><code>/usr/bin/php -q /path/to/YourSubscribePage/admin/index.php -p processqueue -c /path/to/YourSubscribePage/config/config.php &gt;/dev/null</code></p>

<h2 id="and-then"><a href="https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/#and-then">And then...</a></h2>

<p>That <em>should</em> be it.  There are lots of options which you can fiddle around with. But the above should be enough to get your first newsletter out.</p>

<p>Huge thanks to <a href="https://dcameron.me.uk/">Duncan Cameron</a> for graciously answering my noddy questions and helping me out with the config.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53583&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/using-phplist-for-a-blogs-newsletter/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[WordPress - Sic Transit Gloria Mundi]]></title>
		<link>https://shkspr.mobi/blog/2024/10/wordpress-sic-transit-gloria-mundi/</link>
					<comments>https://shkspr.mobi/blog/2024/10/wordpress-sic-transit-gloria-mundi/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 21 Oct 2024 11:34:59 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpdrama]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53533</guid>

					<description><![CDATA[Why do so many vastly-wealthy tech personalities go mad?  My ideal job involves being employed by a millionaire tech-bro. Just before they get on stage, or moments before they file a lawsuit, or an instant before they publish their thought leadership - I will appear to them. I will be dressed in rags, body smeared with excrement, weeping sores blotching my face. I will sidle up to them, lean…]]></description>
										<content:encoded><![CDATA[<p>Why do so many vastly-wealthy tech personalities go mad?</p>

<p>My ideal job involves being employed by a millionaire tech-bro. Just before they get on stage, or moments before they file a lawsuit, or an instant before they publish their thought leadership - I will appear to them. I will be dressed in rags, body smeared with excrement, weeping sores blotching my face. I will sidle up to them, lean down, and whisper into their ear "<i lang="la">Sic Transit Gloria Mundi!</i>"</p>

<p>This used to be the way, of course. When a new Pope or Emperor was paraded through the streets, the people cheered and the acolytes coo'd. But someone would chant at them in Latin, "Thus passes all Earthly glory."</p>

<p>The sun sets on every empire. Each god-king was eventually proved to be mortal. The evil that men do lives after them and the good is oft interred within their bones. And so on. We know this. No one is perfect all the time. Every genius has a moment of idiocy.</p>

<p>For small projects, it makes sense to have only one gaffer. All the work passes through him. Too many cooks poison the well.</p>

<p>As projects get bigger, one person doesn't scale. It is functionally impossible to know everything, see everything, please everyone. Yet the sole arbiter remains. We (almost-jokingly) call this position BDFL. The Benevolent Dictator For Life.</p>

<p>But BDFL only works if the D is genuinely B. Otherwise the FL becomes <abbr title="Fuck My Life">FML</abbr>.</p>

<p>It must be psychologically difficult being responsible for a mega-project. I certainly couldn't do it. If you're wasting time reading this blog post, <em>you</em> almost certainly couldn't do it.  I like my friends to challenge my occasional missteps. I want people to be somewhat honest to my face. I can't imagine what it would do to my ego to receive endless praise. Of course I'd tune out the negative voices.</p>

<p>This isn't to excuse their excesses. Nor to fully demystify their demagoguery. I just want them to have good mental health so their public meltdowns don't reverberate through the æther, infecting us all with their psychic fallout.</p>

<p>*<em>sigh</em>* I'd rather not be blogging about blogging.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53533&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/wordpress-sic-transit-gloria-mundi/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Import JetPack Statistics into Koko]]></title>
		<link>https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/</link>
					<comments>https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 18 Oct 2024 11:34:10 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Koko Analytics]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53483</guid>

					<description><![CDATA[I&#039;ve quit JetPack stats. I&#039;ve moved to Koko Analytics. All the stats code is self hosted, it is privacy preserving, and the codebase is small and simple.  But I am vain. I want all my old JetPack stats to appear in Koko so I can look back on the glory days of blogging.  Koko has two main tables.  The first is a summary table called wpbp_koko_analytics_site_stats :       date   visitors  …]]></description>
										<content:encoded><![CDATA[<p>I've <a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/">quit JetPack stats</a>. I've moved to <a href="https://www.kokoanalytics.com/">Koko Analytics</a>. All the stats code is self hosted, it is privacy preserving, and the codebase is small and simple.</p>

<p>But I am vain. I want all my old JetPack stats to appear in Koko so I can look back on the glory days of blogging.</p>

<p>Koko has two main tables.  The first is a summary table called <code>wpbp_koko_analytics_site_stats</code> :</p>

<table>
<thead>
<tr>
  <th align="center">date</th>
  <th align="center">visitors</th>
  <th align="center">pageviews</th>
</tr>
</thead>
<tbody>
<tr>
  <td align="center">2009-10-30</td>
  <td align="center">25</td>
  <td align="center">47</td>
</tr>
<tr>
  <td align="center">2009-10-31</td>
  <td align="center">70</td>
  <td align="center">86</td>
</tr>
<tr>
  <td align="center">2009-11-01</td>
  <td align="center">61</td>
  <td align="center">72</td>
</tr>
</tbody>
</table>

<p>That's the total number of visitors and page views for each date.</p>

<p>Then there's a more detailed breakdown at <code>wpbp_koko_analytics_post_stats</code></p>

<table>
<thead>
<tr>
  <th align="center">date</th>
  <th align="center">id</th>
  <th align="center">visitors</th>
  <th align="center">pageviews</th>
</tr>
</thead>
<tbody>
<tr>
  <td align="center">2009-10-30</td>
  <td align="center">123</td>
  <td align="center">2</td>
  <td align="center">2</td>
</tr>
<tr>
  <td align="center">2009-10-30</td>
  <td align="center">456</td>
  <td align="center">5</td>
  <td align="center">6</td>
</tr>
<tr>
  <td align="center">2009-10-30</td>
  <td align="center">789</td>
  <td align="center">1</td>
  <td align="center">1</td>
</tr>
</tbody>
</table>

<p>That shows every individual post's number of views and visitors per day.</p>

<p>WordPress's database is MySQL. It can handle CSV imports. So, given these tables are pretty simple, it is possible to get the old WordPress stats, convert them to CSV, and then import them.</p>

<p>Let's go!</p>

<p>As described <a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/">in a previous post</a>, the JetPack stats API is fairly basic. It doesn't differentiate between visitors and pageviews. So, for this import, we'll pretend they're the same.</p>

<p>This will be a 4 step process.</p>

<h2 id="1-get-all-your-stats-in-json-format"><a href="https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/#1-get-all-your-stats-in-json-format">1. Get all your stats in JSON format</a></h2>

<p>This code loops through your stats and downloads a JSON file for each one.</p>

<p>You will need:</p>

<ul>
<li>Your API key - find it at <a href="https://apikey.wordpress.com/">https://apikey.wordpress.com/</a></li>
<li>Your blog's web address - I assume you know this</li>
<li>The earliest date you have for JetPack - you will need to find this yourself</li>
</ul>

<pre><code class="language-python">import requests
import datetime
import os
import json

# Directory to save the JSON files
save_dir = "jetpack_stats"
os.makedirs(save_dir, exist_ok=True)

# URL of the API
base_url = "https://stats.wordpress.com/csv.php?api_key=123456789012"+\
           "&amp;blog_uri=https://example.com/"+\
           "&amp;table=postviews"+\
           "&amp;days=1"+\
           "&amp;format=json"+\
           "&amp;limit=-1"+\
           "&amp;end="

# Make API call and save the response
def fetch_and_save_json(date):
    # Format the date as ISO8601 (YYYY-MM-DD)
    formatted_date = date.isoformat()

    # Make the API call
    url = f"{base_url}{formatted_date}"
    response = requests.get(url)

    if response.status_code == 200:
        data = response.json()
        file_name = f"{formatted_date}.json"
        file_path = os.path.join(save_dir, file_name)
        with open(file_path, "w") as f:
            json.dump(data, f, indent=4)

        print(f"Saved {formatted_date}")
    else:
        print(f"Failed! {formatted_date} status code: {response.status_code}")

# Iterate over a date range
start_date = datetime.date(2020,  1 , 1)
end_date   = datetime.date(2024, 10, 30)

# Loop through all dates 
current_date = start_date
while current_date &lt;= end_date:
    fetch_and_save_json(current_date)
    current_date += datetime.timedelta(days=1)
</code></pre>

<h2 id="2-generate-the-individual-posts-stats"><a href="https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/#2-generate-the-individual-posts-stats">2. Generate The Individual Posts' Stats</a></h2>

<p>This takes those JSON files and creates a single CSV ready to upload to <code>wpbp_koko_analytics_post_stats</code>.</p>

<pre><code class="language-python">import os
import json
import csv

# Directory where the JSON files are stored
json_dir = "jetpack_stats"

# List to hold the loaded data
all_data = []

json_files = sorted( [ file for file in os.listdir( json_dir ) if file.endswith( ".json" ) ] )

# Loop through all files in the directory
for file_name in json_files :
    if file_name.endswith( ".json" ) :
        file_path = os.path.join(json_dir, file_name)
        with open(file_path, "r") as json_file :
            data = json.load(json_file)
            all_data.append(data)  # Add the data to the list

print(f"Total files loaded: {len(all_data)}")
with open( "wpbp_koko_analytics_post_stats.csv", "w", newline="") as csvfile:
    csvwriter = csv.writer( csvfile, delimiter="," )
    for stat in all_data:
        for views in stat[0]["postviews"] :
            csvwriter.writerow( [ stat[0]["date"], views["post_id"], views["views"], views["views"] ] )
</code></pre>

<h2 id="3-generate-the-total-site-views"><a href="https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/#3-generate-the-total-site-views">3. Generate the total site views</a></h2>

<p>It <em>is</em> possible to get this separately from the JetPack API using <code>&amp;table=views</code> - but that's a lot more API calls. So we're just going to sum it up instead 😄</p>

<p>This, again, inserts a dummy value for visitors.</p>

<pre><code class="language-python">import pandas as pd

input_csv  = "wpbp_koko_analytics_post_stats.csv"
output_csv = "wpbp_koko_analytics_site_stats.csv"

column_names = ['Date', 'Post ID', 'Visitors', 'Page Views']
df = pd.read_csv( input_csv, names=column_names )

# Group by Date and sum the Page Views
df_grouped = df.groupby( "Date" )["Page Views"].sum().reset_index()

# Add a new column with a copy of the Page Views
df_grouped['Visitors'] = df_grouped['Page Views']

# Rename the Page Views column to Total Page Views
df_grouped = df_grouped.rename(columns={"Page Views": "Total Page Views"})

# Write the dataframe to the output CSV file
df_grouped.to_csv( output_csv, index=False,  header=False )
</code></pre>

<h2 id="4-upload-to-mysql"><a href="https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/#4-upload-to-mysql">4. Upload to MySQL</a></h2>

<p>You're on your own here, Sparky. If you have something like PHPMyAdmin, you should be able to load the file in directly. Anything else… good luck!</p>

<p>Once done, your stats dashboard should be filled with historic data.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/10/koko-fs8.png" alt="Graph showing page views over time." width="1024" height="455" class="aligncenter size-full wp-image-53490">

<p>Huge thanks to <a href="https://www.kokoanalytics.com/">Koko Analytics</a> for providing such a great tool and answering my questions.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53483&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/import-jetpack-statistics-into-koko/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Liberate your daily statistics from JetPack]]></title>
		<link>https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/</link>
					<comments>https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 17 Oct 2024 11:34:16 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[jetpack]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53473</guid>

					<description><![CDATA[Because Ma.tt continues to burn all of the goodwill built up by WordPress, and JetPack have decided to charge a ridiculous sum for their statistics, I&#039;ve decided to move to a new stats provider.  But I don&#039;t want to lose all the statistics I&#039;ve built up over the years.  How do I download a day-by-day export of my JetPack stats?  Luckily, there is an API for downloading all your JetPack stats! …]]></description>
										<content:encoded><![CDATA[<p>Because Ma.tt continues to burn all of the goodwill built up by WordPress, and JetPack have decided to charge a ridiculous sum for their statistics, I've decided to move to a new stats provider.  But I don't want to lose all the statistics I've built up over the years.</p>

<p>How do I download a day-by-day export of my JetPack stats<sup id="fnref:dl"><a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/#fn:dl" class="footnote-ref" title="When people ask on the official support forum, they're told to privately contact JetPack. There's a help page which shows how to download a summary. But I couldn't find anything more fine-grained…" role="doc-noteref">0</a></sup>?</p>

<p>Luckily, there is <a href="https://stats.wordpress.com/csv.php">an API for downloading all your JetPack stats</a>!</p>

<p>First, get your API key by visiting <a href="https://apikey.wordpress.com/">https://apikey.wordpress.com/</a> - it should be a 12 character string. For this example, I'm going to use 123456789012. You will need to use your own API key.</p>

<p>There is some brief documentation on that page. Here are the bits we are interested in:</p>

<pre><code class="language-_">api_key     String    A secret unique to your WordPress.com user account.
blog_uri    String    The full URL to the root directory of your blog. Including the full path.
table       String    One of views, postviews, referrers, referrers_grouped, searchterms, clicks, videoplays.
end         String    The last day of the desired time frame. Format is 'Y-m-d' (e.g. 2007-05-01) and default is UTC date.
days        Integer   The length of the desired time frame. Default is 30. "-1" means unlimited.
limit       Integer   The maximum number of records to return. Default is 100. "-1" means unlimited. If days is -1, limit is capped at 500.
format      String    The format the data is returned in, 'csv', 'xml' or 'json'. Default is 'csv'.
</code></pre>

<p>In order to get all of the statistics from a single day, the URl is:</p>

<pre><code class="language-_">https://stats.wordpress.com/csv.php?api_key=123456789012
     &amp;blog_uri=https://shkspr.mobi/blog/
     &amp;table=postviews
     &amp;end=2024-10-07
     &amp;days=1
     &amp;limit=-1
</code></pre>

<p>That gets all of the statistics from <em>one</em> specific day. The <code>limit=-1</code> means it will retrieve all the records of that day<sup id="fnref:day"><a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/#fn:day" class="footnote-ref" title="The maximum number of records for a specific day in my dataset was 978." role="doc-noteref">1</a></sup>.</p>

<p>That will get you a CSV which looks like:</p>

<pre><code class="language-csv">"date","post_id","post_title","post_permalink","views"
"2024-10-09",0,"Home page","https://shkspr.mobi/blog/",59
"2024-10-09",42171,"Review: HP's smallest laser printer - M140w + Linux set up","https://shkspr.mobi/blog/2022/04/review-hps-smallest-laser-printer-m140w-linux-set-up/",7
"2024-10-09",49269,"No, Oscar Wilde did not say ""Imitation is the sincerest form of flattery that mediocrity can pay to greatness""","https://shkspr.mobi/blog/2024/01/no-oscar-wilde-did-not-say-imitation-is-the-sincerest-form-of-flattery-that-mediocrity-can-pay-to-greatness/",7
"2024-10-09",53333,"The Cleaner 🆚 Der Tatortreiniger - Series 3","https://shkspr.mobi/blog/2024/10/the-cleaner-%f0%9f%86%9a-der-tatortreiniger-series-3/",7
"2024-10-09",49943,"Solved! ""Access Point Name settings are not available for this user""","https://shkspr.mobi/blog/2024/03/solved-access-point-name-settings-are-not-available-for-this-user/",7
"2024-10-09",43690,"WhatsApp Web for Android - a reasonable compromise?","https://shkspr.mobi/blog/2022/11/whatsapp-web-for-android-a-reasonable-compromise/",5
</code></pre>

<p>You can also get a JSON file using <code>&amp;format=json</code>, although it doesn't contain the permalinks.</p>

<pre><code class="language-json">[
    {
        "date": "2024-10-09",
        "postviews": [
            {
                "post_id": 0,
                "post_title": "",
                "permalink": "",
                "views": 59
            },
            {
                "post_id": 49269,
                "post_title": "No, Oscar Wilde did not say \"Imitation is the sincerest form of flattery that mediocrity can pay to greatness\"",
                "permalink": "",
                "views": 9
            },
            {
                "post_id": 42171,
                "post_title": "Review: HP's smallest laser printer - M140w + Linux set up",
                "permalink": "",
                "views": 7
            },
</code></pre>

<p>From there, I wrote a scrap of Python to download every single date individually.</p>

<pre><code class="language-python">import requests
import datetime
import os
import json

# Directory to save the JSON files
save_dir = "jetpack_stats"
os.makedirs(save_dir, exist_ok=True)

# URL of the API
base_url = "https://stats.wordpress.com/csv.php?api_key=123456789012"+\
           "&amp;blog_uri=https://example.com/"+\
           "&amp;table=postviews"+\
           "&amp;days=1"+\
           "&amp;format=json"+\
           "&amp;limit=-1"+\
           "&amp;end="

# Make API call and save the response
def fetch_and_save_json(date):
    # Format the date as ISO8601 (YYYY-MM-DD)
    formatted_date = date.isoformat()

    # Make the API call
    url = f"{base_url}{formatted_date}"
    response = requests.get(url)

    if response.status_code == 200:
        data = response.json()
        file_name = f"{formatted_date}.json"
        file_path = os.path.join(save_dir, file_name)
        with open(file_path, "w") as f:
            json.dump(data, f, indent=4)

        print(f"Saved {formatted_date}")
    else:
        print(f"Failed! {formatted_date} status code: {response.status_code}")

# Iterate over a date range
start_date = datetime.date(2023,  1 , 1)
end_date   = datetime.date(2024, 10, 30)

# Loop through all dates 
current_date = start_date
while current_date &lt;= end_date:
    fetch_and_save_json(current_date)
    current_date += datetime.timedelta(days=1)
</code></pre>

<p>You'll need to manually find the earliest date for which your blog has statistics.</p>

<p>Running the code is a little slow. Expect about 3 minutes per year of data. I'm sure you could parallelise it if you really needed to.</p>

<p>Now, for my next trick, how do I import these data into a <em>new</em> stats plugin? That's tomorrow's blog post!</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:dl">
<p>When people ask on the official support forum, they're <a href="https://wordpress.org/support/topic/how-do-we-export-all-stats-data-held-on-jetpack-servers/">told to privately contact JetPack</a>. There's a help page which shows <a href="https://wordpress.com/support/stats/#download-stats">how to download a summary</a>. But I couldn't find anything more fine-grained than that.&nbsp;<a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/#fnref:dl" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:day">
<p>The maximum number of records for a specific day in my dataset was 978.&nbsp;<a href="https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/#fnref:day" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53473&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/liberate-your-daily-statistics-from-jetpack/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[How to make Markdown Footnotes start at Zero in WordPress]]></title>
		<link>https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 11 Oct 2024 11:34:59 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[footnotes]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=52307</guid>

					<description><![CDATA[As a dedicated and professional computer scientician, I believe that all indices must start at zero. Not one, not two, but zero.  The zeroth element is sacrosanct to our creed; for in the beginning there was nothing.  If you&#039;re using WordPress&#039;s JetPack, it uses an ancient version of Markdown Extra.  You can either monkeypatch this, or install a separate Markdown plugin.  I&#039;ve patched my fork of…]]></description>
										<content:encoded><![CDATA[<p>As a dedicated and professional computer scientician<sup id="fnref:true"><a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fn:true" class="footnote-ref" title="I've even got certificates in it!" role="doc-noteref">0</a></sup>, I believe that all indices <em>must</em> start at zero. Not one, not two, but zero<sup id="fnref:five"><a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fn:five" class="footnote-ref" title="Five is right out!" role="doc-noteref">1</a></sup>.</p>

<p>The zeroth<sup id="fnref:zeroth"><a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fn:zeroth" class="footnote-ref" title="Or is it &quot;noughtst&quot;?" role="doc-noteref">2</a></sup> element is sacrosanct to our creed; for in the beginning there was <em>nothing</em>.</p>

<p>If you're using WordPress's JetPack, it uses an ancient version of <a href="https://github.com/michelf/php-markdown">Markdown Extra</a>.  You can either monkeypatch this, or <a href="https://codeberg.org/jeffmcneill/markdown-extra-unofficial">install a separate Markdown plugin</a>.</p>

<p>I've <a href="https://codeberg.org/edent/markdown-extra-unofficial/src/branch/edent-update">patched my fork of it</a> in two specific places.</p>

<p>Firstly, I set <code>$this-&gt;footnote_counter = 0;</code> in the initial config of the footnotes.</p>

<p>Secondly, I changed the display so that the ordered list began from zero: <code>&lt;ol start="0"&gt;</code></p>

<p>Wait… should that be zerothly and firstly?</p>

<p>There's no way to change footnote links to symbols like * or ♪. Perhaps I'll add that next<span style="display:none;"><sup id="fnref:hide"><a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fn:hide" class="footnote-ref" title="OK, maybe there is a way. But it isn't particularly easy or automated." role="doc-noteref">3</a></sup></span><sup id="fnref:hide"><a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fn:hide" class="footnote-ref" title="OK, maybe there is a way. But it isn't particularly easy or automated." role="doc-noteref">😉</a></sup>?</p>

<p>Anyway, I enjoy hacking around on my theme.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:true">
<p>I've even got certificates in it!&nbsp;<a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fnref:true" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:five">
<p><a href="https://youtu.be/SNTzOBKs1bA?t=74">Five is <em>right</em> out!</a>&nbsp;<a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fnref:five" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:zeroth">
<p>Or is it "noughtst"?&nbsp;<a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fnref:zeroth" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:hide">
<p>OK, maybe there is a way. But it isn't particularly easy or automated.&nbsp;<a href="https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/#fnref:hide" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=52307&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/how-to-make-markdown-footnotes-start-at-zero-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[WordPress - Display hook action priority in the dashboard]]></title>
		<link>https://shkspr.mobi/blog/2024/08/wordpress-display-hook-action-priority-in-the-dashboard/</link>
					<comments>https://shkspr.mobi/blog/2024/08/wordpress-display-hook-action-priority-in-the-dashboard/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 31 Aug 2024 11:34:14 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=52230</guid>

					<description><![CDATA[If your WordPress site has lots of plugins, it&#039;s sometimes difficult to keep track of what is manipulating your content. Ever wondered what priority all your various actions and filters have? This is a widget which will show you which actions are registered to your blog&#039;s hooks, and their priority order.  It looks like this:    Stick this code in your theme&#039;s functions.php or in its own plugin. …]]></description>
										<content:encoded><![CDATA[<p>If your WordPress site has lots of plugins, it's sometimes difficult to keep track of what is manipulating your content. Ever wondered what priority all your various actions and filters have? This is a widget which will show you which actions are registered to your blog's hooks, and their priority order.</p>

<p>It looks like this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/08/priorities-fs8.png" alt="List of actions with various priorities." width="600" height="599" class="aligncenter size-full wp-image-52231">

<p>Stick this code in your theme's <code>functions.php</code> or in its own plugin.</p>

<pre><code class="language-php">function edent_priority_dashboard_widget_contents() {
    global $wp_filter; 
    //  Change this to the hook you're interested in
    $hook_name = "the_content";
    if ( isset( $wp_filter[$hook_name] ) ) {

        //  Display the hook name in the widget
        echo "&lt;h3&gt;{$hook_name}&lt;/h3&gt;";

        //  Start a list
        echo "&lt;ul&gt;";

        //  Loop through the callbacks in priority order
        foreach ( $wp_filter[$hook_name]-&gt;callbacks as $priority =&gt; $callbacks ) {
            echo "&lt;li&gt;Priority: {$priority}&lt;ul&gt;";

            foreach ( $callbacks as $callback ) {
                //  Some callbacks are arrays
                if ( is_array( $callback["function"] ) ) {
                    if (is_object($callback["function"][0])) {
                        $callback_info = get_class($callback["function"][0]) . '::' . $callback["function"][1];
                    } else {
                        $callback_info = $callback["function"][0] . '::' . $callback["function"][1];
                    }
                } else {
                    $callback_info = $callback["function"];
                }
                //  Show the information
                echo "&lt;li&gt;Callback: {$callback_info}&lt;/li&gt;";
            }
            echo "&lt;/ul&gt;&lt;/li&gt;";
        }
        echo '&lt;/ul&gt;';

    } 
    else {
        echo "No filters found for hook: {$hook_name}";
    }

    //  Scrap of CSS to ensure list items display properly on the dashboard
    $priority_css_code = "#edent_dashboard_widget ul { list-style: circle; padding: 1em; }";
    //  Inline the CSS
    echo "&lt;link rel=\"stylesheet\" type=\"text/css\" href=\"data:text/css;base64," . 
        base64_encode($priority_css_code) . "\"&gt;";

}

//  Register the widget with the admin dashboard
function edent_register_dashboard_widget() {
    wp_add_dashboard_widget(
        "edent_dashboard_widget",   //  ID of the widget
        "Priorities",   //  Title of the widget
        "edent_priority_dashboard_widget_contents"  //  Function to run
    );
}
add_action( "wp_dashboard_setup", "edent_register_dashboard_widget" );
</code></pre>

<h2 id="why"><a href="https://shkspr.mobi/blog/2024/08/wordpress-display-hook-action-priority-in-the-dashboard/#why">Why?</a></h2>

<p>WordPress lets you <a href="https://developer.wordpress.org/plugins/hooks/">add actions and filters to hooks</a>.  For example, whenever your blog wants to show some content, a hook of <code>the_content</code> is run.</p>

<p>You can add an action to run a function when that happens. For example, if you want to make all the text in your blog posts uppercase, you could add this to your theme or plugin:</p>

<pre><code class="language-php">function lower_case_everything( $content ) {
   return strtolower( $content );
}
add_filter( 'the_content', 'lower_case_everything', 99 );
</code></pre>

<p>The <code>add_filter</code> says "When the hook called <code>the_content</code> is fired, run the function <code>lower_case_everything</code>, with a priority of 99".  The lower the number, the sooner the function is run.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=52230&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/08/wordpress-display-hook-action-priority-in-the-dashboard/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Liberate your Markdown posts from JetPack in WordPress]]></title>
		<link>https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 25 Aug 2024 11:34:20 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[jetpack]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=51755</guid>

					<description><![CDATA[A scrap of code which I hope helps you.  Problem  You installed the WordPress JetPack plugin and wrote all your blog posts in Markdown. Now you want to remove JetPack or replace it with a better Markdown parser.  You turn off JetPack&#039;s &#34;Write posts or pages in plain-text Markdown syntax&#34;.  You click edit on a post and see the HTML version of your page. Where did the Markdown version go? …]]></description>
										<content:encoded><![CDATA[<p>A scrap of code which I hope helps you.</p>

<h2 id="problem"><a href="https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#problem">Problem</a></h2>

<p>You installed the WordPress JetPack plugin and wrote all your blog posts in Markdown. Now you want to remove JetPack or replace it with a better Markdown parser.</p>

<p>You turn off JetPack's "Write posts or pages in plain-text Markdown syntax".  You click edit on a post and see the HTML version of your page. Where did the Markdown version go?</p>

<h2 id="background"><a href="https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#background">Background</a></h2>

<p>When you write using JetPack's Markdown plugin, the Markdown version is stored in <code>post_content_filtered</code>. When you hit "publish" or "update", the page is parsed as Markdown and the HTML output is stored in <code>post_content</code>.</p>

<p>When you hit "edit", the <code>post_content_filtered</code> version is loaded into the editor - and the process starts again.</p>

<h2 id="solution"><a href="https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#solution">Solution</a></h2>

<p>When you edit a post, replace the content with the filtered version, then delete the filtered version.</p>

<p>Place this code in your theme's <code>functions.php</code>.</p>

<pre><code class="language-php">function edit_markdown_content( $content, $id ) {
    $post = get_post( $id );
    if ( $post &amp;&amp; ! empty( $post-&gt;post_content_filtered ) ) {
        //  Get the Markdown version
        $markdown = $post-&gt;post_content_filtered;

        //  Delete the post_content_filtered version
        global $wpdb;
        $debug = $wpdb-&gt;query( 
            $wpdb-&gt;prepare(
                "UPDATE $wpdb-&gt;posts SET `post_content_filtered` = '' WHERE `wp_posts`.`ID` = %d",
                                                                                              $id
            )
        );

        //  Replace the post_content with the Markdown version
        $post-&gt;post_content = $markdown;

        //  Send it to the editor with a message saying that it was restored, along with the date of restoration
        return "&lt;!-- Restored from post_content_filtered \n" . date("c") . "\n--&gt;" . $post-&gt;post_content;
    }
    return $post-&gt;post_content;
}
add_filter( "edit_post_content", "edit_markdown_content", 1, 2 );
</code></pre>

<p>I adapted it from <a href="https://github.com/terrylinooo/githuber-md/blob/5ae517a549600f719645d35baf30b29a8069ebcc/src/Controllers/Markdown.php#L1111">WP Githuber MD</a></p>

<h2 id="direct-mysql"><a href="https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#direct-mysql">Direct MySQL</a></h2>

<p>If you want to automatically convert all your posts, you can edit your database directly.</p>

<pre><code class="language-mysql">UPDATE wp_posts
SET 
    post_content = post_content_filtered,
    post_content_filtered = ''
WHERE post_content_filtered IS NOT NULL AND post_content_filtered&lt;&gt;'';
</code></pre>

<h2 id="warning"><a href="https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/#warning">Warning</a></h2>

<p>If you do not have a Markdown parser installed, posts will come out looking *very* strange.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=51755&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/08/liberate-your-markdown-posts-from-jetpack-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Replace Twitter Embeds with Semantic HTML]]></title>
		<link>https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/</link>
					<comments>https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 24 Aug 2024 11:34:34 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=51484</guid>

					<description><![CDATA[I logged into Twitter using a fresh account last week. No followers, no preferences set. The default experience was an unending slurry of racism and porn.  I don&#039;t care to use Twitter any more. Whatever good that was there is now drowned in a cess-pit of violent filth.  I still have a lot of Tweets embedded on this blog. Using WordPress, it was easy to paste in a link and have it converted to an…]]></description>
										<content:encoded><![CDATA[<p>I logged into Twitter using a fresh account last week. No followers, no preferences set. The default experience was an unending slurry of racism and porn.  I don't care to use Twitter any more. Whatever good that was there is now drowned in a cess-pit of violent filth.</p>

<p>I still have a lot of Tweets embedded on this blog. Using WordPress, it was easy to paste in a link and have it converted to an embed. But I don't want to direct people to a dangerous site.</p>

<p>So here's a somewhat automated way to replace embedded Tweets with good-looking and semantic HTML.  You no longer need to worry about Twitter tracking people if they visit your site. It in-lines all images and avatars so there's no data leakage. Links go direct rather than through the obnoxious t.co service. The HTML is semantic, short, and accessible.</p>

<p><a href="https://github.com/edent/Tweet2Embed">The simple Python code is available on GitHub</a> - feedback welcome!</p>

<h2 id="demos"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#demos">Demos</a></h2>

<p>Here are some examples. You'll see all the links work - to external sites, hashtags, or mentions. Media is loaded, emoji work, alt text is included where available, and the CSS is <em>roughly</em> right.  The number of likes and replies is shown - but the number of retweets isn't always available in the embed API. The number of quotes and bookmarks aren't available.</p>

<h3 id="polls"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#polls">Polls</a></h3>

<style>.social-embed {all: unset;display: block;}.social-embed * {all: unset;display: revert;}.social-embed::after {all: unset;}.social-embed::before {all: unset;}blockquote:not(*) {all: unset;}.social-embed a {cursor: pointer;}blockquote.social-embed {box-sizing: border-box;border: .5px solid;width: 550px;max-width: 100%;font-family: sans-serif;margin: 0;margin-bottom: .5em;padding: 1em;border-radius: 1em;background-color: white;color: black;display: block;}.social-embed-header {display: flex;justify-content: space-between;}.social-embed-user {display: flex;position: relative;align-items: center;text-decoration: none;color: inherit;}.social-embed-avatar {width: 3em;height: 3em;margin-right: .5em;}.social-embed-avatar-circle {border-radius: 100%;}.social-embed-user-names-name {display: flex;align-items: center;font-weight: bold;margin: 0;}.social-embed-text {margin-top: .5em;}.social-embed-footer {display: flex;align-items: center;justify-content: space-between;}.social-embed-logo {width: 3em;}.social-embed-hr {border: .1px solid;margin: .5em 0 .5em 0;}.social-embed-meta {text-decoration: none !important;color: unset !important;}.social-embed-reply {display: block;}.social-embed-text a, .social-embed-footer time {color: blue;text-decoration: underline;}.social-embed-media, .social-embed-video {border-radius:1em;max-width:100%;}.social-embed-reply{font-size:.75em;display:block;}.social-embed-meter{width: 100%;background: #0005;}</style>

<blockquote class="social-embed" id="social-embed-670060095972245504" lang="en"><header class="social-embed-header"><a href="https://twitter.com/polls" class="social-embed-user"><img class="social-embed-avatar" src="data:image/webp;base64,UklGRuwAAABXRUJQVlA4IOAAAABQBgCdASowADAAPrVWpEunJSOhqrqpWOAWiWUAxQaACJBCAEB6EJ7HdwZ7m9AsQTxW+yk80gC5I/REUAD+5Ij/FsUhuZ/jfEF7U+ofYABMBkF4Sc8d827tC2qwG95CN3fVuuFS/uqP/Fwucurp8KcurrXcBQpkUCdvp40Y29kx8lP8Y45C3t4IcJPYcIDFVl5+L1M3426aJn0CIdA27KAZjABt0TDw3lgHKggxpvOpEjEgBMnQHzq9rFumwbXgCzvqgOwsseDr6msoySerlXwDZWfNYqz4k58dV2tZoAAAAA==" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">polls</p>@polls</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Which Direction?<hr class="social-embed-hr"><label for="poll_1_count">North: (13,835)</label><br><meter class="social-embed-meter" id="poll_1_count" min="0" max="100" low="33" high="66" value="32.6">13835</meter><br><label for="poll_2_count">South: (5,584)</label><br><meter class="social-embed-meter" id="poll_2_count" min="0" max="100" low="33" high="66" value="13.1">5584</meter><br><label for="poll_3_count">East: (4,597)</label><br><meter class="social-embed-meter" id="poll_3_count" min="0" max="100" low="33" high="66" value="10.8">4597</meter><br><label for="poll_4_count">One: (18,469)</label><br><meter class="social-embed-meter" id="poll_4_count" min="0" max="100" low="33" high="66" value="43.5">18469</meter></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/polls/status/670060095972245504" aria-label="245 likes" class="social-embed-meta">❤️ 245</a><a href="https://twitter.com/polls/status/670060095972245504" aria-label="41 replies" class="social-embed-meta">💬 41</a><a href="https://twitter.com/polls/status/670060095972245504" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/polls/status/670060095972245504"><time datetime="2015-11-27T02:02:30.000Z">02:02 - Fri 27 November 2015</time></a></footer></blockquote>

<h3 id="embedded-images"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#embedded-images">Embedded Images</a></h3>

<blockquote class="social-embed" id="social-embed-909106648928718848" lang="en"><header class="social-embed-header"><a href="https://twitter.com/hackaday" class="social-embed-user"><img class="social-embed-avatar" src="data:image/webp;base64,UklGRhACAABXRUJQVlA4IAQCAADQCwCdASowADAAPrVYok8nJSKiI4kA4BaJaQAVwBp2fhY+P/HZw7/CbwMMFMB8cv0T7An6p9Xb0VUlah8+O6yXKQMlWLuIzLuCj+pgz6/1J8XQ8+Mw8iev4nGVzR6MBYiDMSb7XO8AAP7bWCIvhB0cnWLjsM9t3Y50BdjVksLzKG9vSbtMIFqXRvW+O3v92Kb5hL63GKaHy/foRx6BaDD22q/uv7mDZmjPSpa5LYMMNUHlKot6PJ4xU3Q5K6/Pf1ukhwBwbI9JXMIHbWG6QZG60z64jtXi5e/yiXqiaTRvRI33YCBHIyfG5+RfQEeEuwiCp7XEaueyWBa40mOZSZhRHoLPda/360DZE7ce684RLFj0p1ji1hUyoSw82KdLjm0XhI7c6UElTR/vfVFuUhp333w6yzDY/Z7yW0aDAAcQ4v69yJA3s1VhXyCvt2AKrioCiZ6q9/aPMVc3wNrMj03uD8FmUm4+EJo1diQcETu7VhGIn/xYvVE3ErUIp5UhTem2lcMpMGG9x3aF6S8XW1/GwfXUKQ+RzoMNkaJNSqLIiI17rUXxPU8467+fxHVQ95NpJCDhgudHwX95tn0l2HIzmap6ALEf6lLOYAJvzuDPq0/1KzYPYEtuQFkHb4tOoJdRX3F9oywy5Dr631wc7065PABvSXMo0+J1xAncVgH0WKxQAAA=" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">hackaday</p>@hackaday</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Can a hacker do YouTube full time? <a href="https://twitter.com/XRobotsUK">@XRobotsUK</a> says yes (with an asterisk) and talks gory details <a href="https://twitter.com/hashtag/HackadayUncon">#HackadayUncon</a> <a href="https://twitter.com/hackaday/status/909106648928718848/photo/1">pic.x.com/7h1ozav0wt</a><a href="https://pbs.twimg.com/media/DJ3Lik3WsAIHGUX.jpg"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a><a href="https://pbs.twimg.com/media/DJ3LnOlWsAEi4o-.jpg"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/hackaday/status/909106648928718848" aria-label="20 likes" class="social-embed-meta">❤️ 20</a><a href="https://twitter.com/hackaday/status/909106648928718848" aria-label="2 replies" class="social-embed-meta">💬 2</a><a href="https://twitter.com/hackaday/status/909106648928718848" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/hackaday/status/909106648928718848"><time datetime="2017-09-16T17:28:10.000Z">17:28 - Sat 16 September 2017</time></a></footer></blockquote>

<h3 id="quote-tweets"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#quote-tweets">Quote Tweets</a></h3>

<blockquote class="social-embed" id="social-embed-1560621791470448642" lang="en"><header class="social-embed-header"><a href="https://twitter.com/edent" class="social-embed-user"><img class="social-embed-avatar" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Whoever buys the <a href="http://gu.com">gu.com</a> domain will effectively get to rewrite history.<br>They can redirect links like these - and change the nature of the content being commented on.<blockquote class="social-embed" id="social-embed-1067447032363794432" lang="en"><header class="social-embed-header"><a href="https://twitter.com/JoyceWhiteVance" class="social-embed-user"><img class="social-embed-avatar" src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4ID4CAABQDACdASowADAAPq1KnkmmJKMhLjv8yMAViUAVJO5ApQV3x9j+gpYwxsJwsuzTWzTPLzTDegfuygB3a1UnkqhyleOJ22EAp2qZX68sMSedc0PdMkSpOfXr0Cy5A3LYvHSQ2b1bNmB2Rew3uAD+6QRmQvnHF8LBpwzdqn5fCVXqfuXEtWhT9E/TZPX2Zv0bk6Uw88bp6SF4WK/Ow3ZYJGSgbesYN0TLbpdtOifl9keMQTUIYkh9YSEWTOkL4+EqUdFzdg334B1S9qBP3UvuBrrNyAyX09E49BJZr5KRUAQScRJvkVpbRKqS3u7JHW83VBJkWT/xer5blmltjAGhOFWZPuqnk5FRwDooQZcDo1NOY+i2gktQGv6B9TqD0oXZqzzQV9aAKdNkcwJpyTEdJL0rFjo1uGwiK8vW/xTMESt/HPxcmDmycZzE2HQMX+CO37tdy4pXJoWHeXoLrU4aOOLQwMgHQXr+9l65EcbpXfTKdziMSCbuICH3dTeb3HaBKLo0kYOUX0HGKhesEpdf3uDolEq4dUujOdgBCUbscqOY3cKPwhNtWqfssn9eaKYWmjC/cHtD6Up6B2PkjH2lLOZRBQDQsrTukvXMyHFRcjTiEB3RHTIgKGxmaMx9w8t1YGvfelOaJtgGpnN6QpkVB7ktTuy4lQc/j9quBIGn3OQ0mOnMv89RjWZJYNTaIy4ccEFRFM7PWUNmA68Azzyk9Uwiq6EC4wFykBGxfmFaumDi3fk4olPNLvUotAVqsAAA" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Joyce Alene</p>@JoyceWhiteVance</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">The Steele Dossier asserted Russian hacking of the DNC was "conducted with the full knowledge &amp; support of Trump &amp; senior members of his campaign.” Trump's war against the FBI &amp; efforts to obstruct make sense if he thought they could prove it. <a href="https://gu.com/p/axa7k/stw">gu.com/p/axa7k/stw</a></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/JoyceWhiteVance/status/1067447032363794432" aria-label="3506 likes" class="social-embed-meta">❤️ 3,506</a><a href="https://twitter.com/JoyceWhiteVance/status/1067447032363794432" aria-label="0 replies" class="social-embed-meta">💬 0</a><a href="https://twitter.com/JoyceWhiteVance/status/1067447032363794432" aria-label="1601 retweets" class="social-embed-meta">♻️ 1,601</a><a href="https://twitter.com/JoyceWhiteVance/status/1067447032363794432"><time datetime="2018-11-27T15:56:19.000Z">15:56 - Tue 27 November 2018</time></a></footer></blockquote></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1560621791470448642" aria-label="11 likes" class="social-embed-meta">❤️ 11</a><a href="https://twitter.com/edent/status/1560621791470448642" aria-label="4 replies" class="social-embed-meta">💬 4</a><a href="https://twitter.com/edent/status/1560621791470448642" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/edent/status/1560621791470448642"><time datetime="2022-08-19T13:36:44.000Z">13:36 - Fri 19 August 2022</time></a></footer></blockquote>

<h3 id="replies"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#replies">Replies</a></h3>

<blockquote class="social-embed" id="social-embed-1095659600420966400" lang="en"><blockquote class="social-embed" id="social-embed-1095653997644574720" lang="en"><header class="social-embed-header"><a href="https://twitter.com/edent" class="social-embed-user"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Working from home is tricky when <a href="https://twitter.com/virginmedia">@virginmedia</a> goes down so hard even its status page falls over.<br>Time for lunch. <a href="https://twitter.com/edent/status/1095653997644574720/photo/1">pic.x.com/mje6nh38cz</a><a href="https://pbs.twimg.com/media/DzSLf6sWsAAGWWH.jpg"><img class="social-embed-media" alt="Oops! something's broken! " src="data:image/webp;base64,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"></a></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1095653997644574720" aria-label="1 likes" class="social-embed-meta">❤️ 1</a><a href="https://twitter.com/edent/status/1095653997644574720" aria-label="0 replies" class="social-embed-meta">💬 0</a><a href="https://twitter.com/edent/status/1095653997644574720" aria-label="1 retweets" class="social-embed-meta">♻️ 1</a><a href="https://twitter.com/edent/status/1095653997644574720"><time datetime="2019-02-13T12:00:43.000Z">12:00 - Wed 13 February 2019</time></a></footer></blockquote><header class="social-embed-header"><a href="https://twitter.com/SkyUK" class="social-embed-user"><img class="social-embed-avatar social-embed-avatar-square" src="data:image/webp;base64,UklGRpYBAABXRUJQVlA4IIoBAAAwCQCdASowADAAPrVKnUonJCKhqq1Q4BaJbAC/Z3cUCDS7Zi7QPQA6WN87sgQYHGgYeKugT77shiN3M8anFf9G/EEwSx89vkshZ/AxKHirOKCMAP78nmfB4hOEQ7ioUeCdd8duHXEEa7zG5Wn1x9tg/F8LwQ47tQqlOC9LnwOnSnJ24M/Ox3Eco8Z3AWan2mKlowNgRvIa9ymmsH95iUfQVc/8JUedqsnL/22MQqzR11KWAsvxHv5CqVKcTFKPz1/JvZ9erdCP/SnfnKr204+8OVA4/jNKCUrEh0EeiytyI9B4Twqe/00LwV1LKLMBIJI37YHW469kbz5nRu4QlQ2/gwTzNI+kQshGsnW/FwHvAJE1kV34jbpZ5/roudpiKCMLC1rT5oUH4HSu62b0+noDv5EtbcAsptwKvlqDR2/sahxNTeCdPLcSFPhnIjfCcxtJkYV4YR0EK/6q6fo7uO66uq95/9IBtexAe6G2NQLjXeLPw3f+67rrZmhRguPsjB4X4CaPIl5+RoAA" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Sky</p>@SkyUK</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text"><small class="social-embed-reply"><a href="https://twitter.com/edent/status/1095653997644574720">Replying to @edent</a></small><a href="https://twitter.com/edent">@edent</a> I can definitely see how this would get in the way of making your day a productive one. Do you find this happens often? If it does, I'd be happy to chat to you about a reliable alternative with us during your lunch break! ☕ PM me for a chat! ^JH</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/SkyUK/status/1095659600420966400" aria-label="0 likes" class="social-embed-meta">❤️ 0</a><a href="https://twitter.com/SkyUK/status/1095659600420966400" aria-label="2 replies" class="social-embed-meta">💬 2</a><a href="https://twitter.com/SkyUK/status/1095659600420966400" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/SkyUK/status/1095659600420966400"><time datetime="2019-02-13T12:22:59.000Z">12:22 - Wed 13 February 2019</time></a></footer></blockquote>

<h3 id="videos"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#videos">Videos</a></h3>

<p>The poster of the video is embedded - the actual MP4 is still loaded off Twitter's site.</p>

<blockquote class="social-embed" id="social-embed-1432768058028875791" lang="en"><header class="social-embed-header"><a href="https://twitter.com/Infoxicador" class="social-embed-user"><img class="social-embed-avatar" src="data:image/webp;base64,UklGRmwCAABXRUJQVlA4IGACAACQCwCdASowADAAPrVSpU6nJCOiJzgIAOAWiWMArDObh9626zvpncDYbdS9Xa3uvdEDeIxBW5hN8ufiJSL/2oc4TPgACjoPAdrcOWCNIznpY6v9kjVt8aGXhzOLJx4CctTTzO70AAD+/hb9/RnXjm7pqZsqRg5SXY588WJIjuYh7ImVtMVXXa5gX6Qq3F+CoQh1QH+9PVZjYlgQ0PYMCe0Qz+do+5mVrw2BGtbqcBBSZDEZb8V8ciJDrVZsFlm+SV6HILVeYBKndA5fyDIk8ga6+T/8gG+24o8zu3KokHfSPz0Q8X0AYRmMia+YQ4WbyI1ltaSgoT7HgNHMa8NkS+zxK6bQakNi2hdqtPD+Bjqdk63Nm+qyK/wDCJNNjaKHjnSM5ucgHC17XpvzuXRtX/SvWNbsGXFfgm99KBVq57SkaR27qGZRWc3JwGVLNO3668lK0HP13t3kwTRGBcwa31GiPTKHt5AwWHiXvnDCTrll1NohIuRLPeV0++IqI4V8ozfCSCuL7Qqh+MGV40HBWmdFJ6cRK4ujJsuqaqLetap1Ji5pZzxgBajTRWcXR6n8sYytEYuZ9pPfXX6fxV3TnYQuSp1Are92yRZRtspPgnO4gO3qZplWedhge3hNOUr//nhfeAHRY7/ZaX2DnDd9V+jc2zYmnve3To5OW06E+oCSp3sjQ83HNYCu+f07bQQRIRqyX849Oz0FQfwdx1W5Xz4njC3uWwiS9eSOOfA8s3o88C7y63f+Bn3Lz28KaP68JXex1IIxiUWvg9VY6Ne97ozK2xAuCY3T18+xzAXtdnYAAA==" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Ruben Casas 🦊</p>@Infoxicador</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Attending my first in person event since the pandemic. <br><br><a href="https://twitter.com/hashtag/TapIntoTwitter">#TapIntoTwitter</a> hosted by <a href="https://twitter.com/gerardsans">@gerardsans</a> and <a href="https://twitter.com/coderinheels">@coderinheels</a><br><br>Nothing better than a cool live demo. <br><br>🤯 <a href="https://twitter.com/Infoxicador/status/1432768058028875791/video/1">pic.x.com/qw1ifom7fh</a><video class="social-embed-video" controls="" src="https://video.twimg.com/ext_tw_video/1432767873504718850/pu/vid/720x960/sS9cLdGn93eUmvKC.mp4?tag=12" poster="data:image/webp;base64,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" width="550"></video></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/Infoxicador/status/1432768058028875791" aria-label="16 likes" class="social-embed-meta">❤️ 16</a><a href="https://twitter.com/Infoxicador/status/1432768058028875791" aria-label="1 replies" class="social-embed-meta">💬 1</a><a href="https://twitter.com/Infoxicador/status/1432768058028875791" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/Infoxicador/status/1432768058028875791"><time datetime="2021-08-31T18:11:39.000Z">18:11 - Tue 31 August 2021</time></a></footer></blockquote>

<h2 id="get-the-code"><a href="https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/#get-the-code">Get The Code</a></h2>

<p><a href="https://github.com/edent/Tweet2Embed">The simple Python code is available on GitHub</a> - feedback welcome!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=51484&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/08/replace-twitter-embeds-with-semantic-html/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		<enclosure url="https://video.twimg.com/ext_tw_video/1432767873504718850/pu/vid/720x960/sS9cLdGn93eUmvKC.mp4?tag=12" length="1546364" type="video/mp4" />

			</item>
		<item>
		<title><![CDATA[Remove unnecessary closing slash on get_the_post_thumbnail() in WordPress]]></title>
		<link>https://shkspr.mobi/blog/2024/07/remove-unnecessary-closing-slash-on-get_the_post_thumbnail-in-wordpress/</link>
					<comments>https://shkspr.mobi/blog/2024/07/remove-unnecessary-closing-slash-on-get_the_post_thumbnail-in-wordpress/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 24 Jul 2024 11:34:13 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=51115</guid>

					<description><![CDATA[I am a pedant. I like it when validators say &#34;nothing to report&#34;. No errors, no warnings, no information messages.  My blog is plagued with messages on the HTML validator saying  Info: Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.  By default, the WordPress function get_the_post_thumbnail() spits out HTML like:  &#60;img width=&#34;1024&#34; height=&#34;593&#34;    …]]></description>
										<content:encoded><![CDATA[<p>I am a pedant. I like it when validators say "nothing to report". No errors, no warnings, no information messages.</p>

<p>My blog is plagued with messages on the HTML validator saying</p>

<blockquote><p><a href="https://github.com/validator/validator/wiki/Markup-%C2%BB-Void-elements#trailing-slashes-directly-preceded-by-unquoted-attribute-values">Info: Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.</a></p></blockquote>

<p>By default, the WordPress function <code>get_the_post_thumbnail()</code> spits out HTML like:</p>

<pre><code class="language-html">&lt;img width="1024" height="593" 
     src="example.jpg"
     alt="whatever"
/&gt;
</code></pre>

<p>That final <code>/</code> is unnecessary. Having it there doesn't do any harm. It doesn't break anything - except my calm - and is safe to leave in place.</p>

<p>Let's get rid of it anyway!</p>

<p>Place this in your theme's <code>functions.php</code> file:</p>

<pre><code class="language-php">//  get_the_post_thumbnail() returns &lt;img ... /&gt; - this removes the unnecessary closing of a void element
function remove_self_closing_slash_from_thumbnail( $html ) {
    //  Check if the string ends with " /&gt;"
    if ( substr( $html, -3 ) === " /&gt;" ) {
        //  Remove the " /&gt;" and add "&gt;"
        $html = substr( $html, 0, -3 ) . "&gt;";
    }
    return $html;
}

add_filter( "post_thumbnail_html", "remove_self_closing_slash_from_thumbnail" );
</code></pre>

<p>That adds a filter to the <a href="https://developer.wordpress.org/reference/hooks/post_thumbnail_html/"><code>post_thumbnail_html</code> hook</a> and edits the string it returns.</p>

<p>There are various ways to approach this, you could load the element into a <code>DOMDocument</code> or have a complex regular expression - but this seems the simplest and safest.</p>

<p>Now, how do I remove the rest of the needless <code>/&gt;</code> that WordPress scatters about?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=51115&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/07/remove-unnecessary-closing-slash-on-get_the_post_thumbnail-in-wordpress/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
