Minimal Social Markup
Tags: html, minimalism, socialmedia
Published: 2022-09-14 14:40:09

Every website and app these days needs so-called “social markup,” metadata for a richer and prettier display in social media and messaging tools. This markup is usually based on the <a href="https://ogp.me/">Open Graph protocol</a>, but Twitter, most notably, has their own metadata (some of which <a href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup">falls back to Open Graph</a>).

If you’re a frontend developer, and maybe even a <a href="https://meiert.com/en/blog/minimal-web-development/">frontend minimalist</a>, you may wonder what the most minimal markup is so as to get a meaningful result. I’ve lately been focusing on this question, reviewing and optimizing my past setup.

If you don’t want to read any further, here’s the absolute minimum you need:

<pre><code>&lt;!-- &lt;head&gt; (and &lt;body&gt;) needed for LinkedIn --&gt;
&lt;head&gt;
  &lt;!-- “twitter:card” and title needed for Twitter --&gt;
  &lt;meta name=twitter:card content=summary_large_image&gt;
  &lt;meta property=og:title content="This is a test title"&gt;
  &lt;!-- Quotes needed for WhatsApp and Signal --&gt;
  &lt;meta property="og:description" name="description" content="This is a test description."&gt;
  &lt;meta property="og:image" content="https://hell.meiert.org/core/png/test.png"&gt;</code></pre>

If you do want to read further, here’s how I’ve arrived at this code.

<h3>Requirements</h3>

First, it’s important to know that I’m an HTML purist and minimalist. I prefer to use the least HTML possible, and therefore <a href="https://meiert.com/en/blog/optional-html/">omit optional markup</a> and love selectors to the degree of <a href="https://meiert.com/en/blog/the-lost-paradigm/">ID- and class-less development</a>. (Not removing all spaces on every page is one exception to this rule—“view-source” is still cool.)

But what are we trying to identify the least amount of markup for? In my mind, whatever is needed to:

<ul>
<li>show the title for the page in question;</li>
<li>display an image;</li>
<li>show the description (optional).</li>
</ul>

Where should this all work? For me—your mileage may vary—this social markup should be displayed properly on the following platforms and apps:

<ul>
<li>Twitter (<a href="https://cards-dev.twitter.com/validator">tester</a> <ins>[currently unreliable]</ins>)</li>
<li>LinkedIn (<a href="https://www.linkedin.com/post-inspector/">tester</a>)</li>
<li>Facebook (<a href="https://developers.facebook.com/tools/debug/">tester</a>)</li>
<li>Signal</li>
<li>WhatsApp</li>
</ul>

<em>Personally, I care about some other networks, too (like XING), and I would care more about other messengers, if I used them (like Telegram), but I’ve been working with kind of a bet here that other networks and apps show a similar behavior as the ones listed. So far, this seems to work. Please let me know about major platforms that show a different behavior (as well as any issues)!</em>

<h3>Social Markup</h3>

The markup for these requirements is fairly easy to identify.

For the title, the <code>title</code> element suffices everywhere but on Twitter (why!). To produce “valid” Twitter card markup, you can use <code>og:title</code>:

<pre><code>&lt;meta property=og:title content="This is a test title"&gt;</code></pre>

To display an image, Twitter also <em>needs</em> <code>twitter:card</code> markup, which also controls the size of the image (cf. <code>summary</code> and <code>summary_large_image</code>):

<pre><code>&lt;meta name=twitter:card content=summary_large_image&gt;
&lt;meta property=og:image content=https://hell.meiert.org/core/png/test.png&gt;</code></pre>

To show the description, slap <code>property=og:description</code> on an existing <code>description</code> element (but, <a href="https://twitter.com/AmierOSaleh/status/1547715147875041280">thanks Amier</a>, <a href="https://snook.ca/archives/html_and_css/open-graph-and-sharing-tags">mind the order</a>):

<pre><code>&lt;meta property=og:description name=description content="This is a test description."&gt;</code></pre>

That leads to the following most minimal markup (following my preferred source order):

<pre><code>&lt;meta name=twitter:card content=summary_large_image&gt;
&lt;meta property=og:title content="This is a test title"&gt;
&lt;meta property=og:description name=description content="This is a test description."&gt;
&lt;meta property=og:image content=https://hell.meiert.org/core/png/test.png&gt;</code></pre>

<h3>Problems</h3>

But, this alone doesn’t do it, even though it’s valid (<a href="https://validator.w3.org/">validate</a> <a href="https://gist.github.com/j9t/e9080557b3e312842b977b115fdef358">the gist</a>) and matches the big players’ specs.

One problem relates to the inability of messenger apps (!) to retrieve description and image, if the respective attributes aren’t put in quotes. (When I still used WhatsApp, I contacted them three times about the image issue, providing test pages and all, but they just dropped it.)

Another problem is social markup not being identified properly, for example by LinkedIn, if it’s not following a <code>&lt;head&gt;</code> start tag.

Both, to spell it out, are <strong>pretty massive, pretty embarrassing bugs</strong>, because both is valid HTML. That is, this code is proper, in conformance with the HTML specifications. (You’re professionals—fix this.)

Both, then, leads to the markup shared in the beginning:

<pre><code>&lt;head&gt;
  &lt;meta name=twitter:card content=summary_large_image&gt;
  &lt;meta property=og:title content="This is a test title"&gt;
  &lt;meta property="og:description" name="description" content="This is a test description."&gt;
  &lt;meta property="og:image" content="https://hell.meiert.org/core/png/test.png"&gt;</code></pre>

❧ And this, to the best of my knowledge, isn’t just minimal, it’s <em>the most minimal</em> social markup.

<em>What I think about this? I already mentioned how upset (but <a href="https://meiert.com/en/blog/critical-frontend-development/">not surprised</a>) I am that <a href="https://meiert.com/en/blog/write-html/">HTML is treated like XHTML</a> and that valid HTML—with no <code>&lt;head&gt;</code> tag, no quotes—isn’t fully supported. But I also believe this markup is still too much—in short, Twitter should make use of page titles (<code>title</code> element) and follow Open Graph (including dumping <code>twitter:card</code>), and all social markup consumers should respect meta descriptions. Then the most minimal markup was to add an <code>og:image</code>—because that wouldn’t otherwise be on a page.</em>