Inside the head of an HTML document
Tags: html, seo, webdev
Published: 2022-05-03 01:13:06


In a HTML document, the `<head>` is the place where you put everything that's not content. This is where you tell the browser how to render your page and what other files like CSS or JS or fonts to download. It's also where you tell a search bot or a social media website like Facebook or Twitter about your website.

Let's walk through one by one all the things you should include in your `<head>`.

## Browser Directives

First up is `<meta charset="utf-8" />` . It directs the browser to treat all your HTML content as UTF-8 and not ASCII or some character encoding such as [ISO-8859-1](https://en.wikipedia.org/wiki/ISO/IEC_8859-1). I don't think this is strictly necessary if you already have `<!DOCTYPE html>` at the top of the file specifying that this document is an HTML5 document. HTML5 only supports UTF-8. And even if you remove the doctype and include `<meta charset="ISO-8859-1" />` , Chrome still treats it as UTF-8 but other browsers might not leading to potentially unpredictable behavior. So, the consensus is that you should always include this tag.

A mobile-optimized website should include:

```html
<meta name="viewport" content="width=device-width, initial-scale=1" />
```

Without this tag, the mobile browser might render the page at desktop width say 1200px and then, scale the page down to fit the actual width of the device likely something much smaller like 390px. It will end up looking super zoomed out. With this tag however, things work as expected. The media query breakpoints you've set for lower widths will return true and the page will render as you intend it to on a smaller device.

## SEO

Then, we have `<title>` which controls the text in the tab bar of the browser. It's also very important for SEO. It ends up being the Google search result's title. For SEO reasons, it is recommended that it's as close to 60 characters as possible. It also ends up being the default name under which the bookmark gets saved as in a user's browser.

`<meta name="description" content="...">` is important for SEO reasons as well. Recommend length is 155-160 characters.

I like to include `<meta name="robots" content="follow, index" />` although the default behavior of most search engine bots is to follow links and index all pages so technically, it's optional but doesn't hurt to be explicit.

The canonical URL is really important for SEO reasons:

```html
<link rel="canonical" href="https://yourwebsite.com/article-title" />
```

It lets the search engine know that canonical URL for the content on this page is the value specified using this tag. That way, I can syndicate this blogpost on dev.to and Medium but still have Google direct people to this page when my content ranks highly for a search keyword. So your actual website ends up getting the traffic rather than dev.to or Medium. Another reason this matters is that [large-scale duplication can lower your search ranking](https://moz.com/learn/seo/canonicalization). With canonical URLs, you are telling Google when something is a duplicate vs. not. Make sure you have consistent canonical URLs across your website: trailing slashes or not? www subdomain or not? HTTPS or not? (pick HTTPS).

What about the keywords tag, `<meta name="keywords" content="seo, search engine optimization"/>` ? I've seen a lot of websites use them but the [consensus in the SEO community](https://ahrefs.com/blog/meta-keywords/) is:

> For 99.9% of people, the meta keywords tag is useless, and filling it out is a waste of time. You should only use it if you have a particular reason to do so, like using it for an internal keyword tagging system or an internal site search.

Most search engines including the biggest one of them all, Google, disregard the tag.

For more SEO tweaks, I generate a [free report here](https://www.seobility.net/en/seocheck/). It'll check many of the things described above. The Google Search Console is also very helpful.

## Social Media

When a link gets shared on Twitter, this is how it looks:

![Twitter social media preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fnlklust66rgc2pn25t.png)
 

The Open Graph meta tags are what the website uses to render this tile.

```html
<meta property="og:title" content="Loops" />
<meta property="og:site_name" content="Loops" />
<meta property="og:url" content="https://loops.quest" />
<meta
  property="og:description"
  content="Analyze Solana transactions. Trace how NFTs and tokens move across multiple accounts."
/>
<meta property="og:type" content="website" />
<meta property="og:image" content="%PUBLIC_URL%/og-image.png" />
```

Title, site_name, URL and description pretty much just correspond to `<title>`, website domain or name, canonical URL, and `<meta name="description">`, respectively.

The type can be a few different types but typically it's either `article` for a blogpost or `website` for an app or an e-commerce website.

For the image, [Facebook recommends](https://developers.facebook.com/docs/sharing/webmasters/images): "1200x630 or larger is preferred (up to 5MB). Stay close to a 1.91:1 aspect ratio to avoid cropping.". But I've found that following the image guidelines is no substitute for actually testing the previews.

To test, I use ngrok to tunnel my local website to the public internet, and copy the URL into [this tool to look at the previews across platforms](https://www.opengraph.xyz/).

Open Graph tags are used by most social platforms, including Twitter. However, for Twitter, you are able to specify Twitter-specific tags as well. Twitter will use `title`, `description` [from the Open Graph tags](https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started#opengraph) so I don't bother re-specifying them. But there are some Twitter-specific tags worth including:

```html
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@_abi_" />
```

Summary card with large image is likely what you want for articles and websites but if you have a video instead, you can specify `player` .

[Twitter's image recommendation for the summary card with large image](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary-card-with-large-image) is slightly different from Facebook: "Images for this Card support an aspect ratio of 2:1 with minimum dimensions of 300x157 or maximum of 4096x4096 pixels. Images must be less than 5MB in size. JPG, PNG, WEBP and GIF formats are supported. Only the first frame of an animated GIF will be used. SVG is not supported."

However, since the aspect ratio is only slightly from Facebook, you can probably skip using a different image.

Besides the testing tool linked earlier, Facebook and Twitter offer their own tools as well: [Facebook](https://developers.facebook.com/tools/debug/)
and [Twitter](https://cards-dev.twitter.com/validator).

## Others

The only remaining thing we must include is a bevy of favicons. Here's [a great article by the author of PostCSS](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs) on what we need and why.

```html
<link rel="icon" href="/favicon.ico" sizes="any" /><!-- 32×32 -->
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" /><!-- 180×180 -->
<link rel="manifest" href="/manifest.webmanifest" />
```

And then in the `manifest.webmanifest` file,

```json
{
  "icons": [
    { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
    { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
  ]
}
```

If your app is a progressive web app i.e. a website that can be installed to the home screen without using an App Store, you should fill out the [manifest file](https://web.dev/add-manifest/) with more detail.