Looks like this article is over a year old, so some of the technical solutions or opinions may be a bit outdated now.

I’m into my second year of Crafting using the excellent new(ish) Craft publishing platform, and getting much more adventurous. One of the things I’ve got setup pretty well now is my document <head>. Thought I’d put it out there for newbies and veterans alike, because it’s always interesting to see how someone else works.

So anyway, here it is:

<!doctype html>
<!--[if IE 8]>         <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
        <meta charset="utf-8"/>
            {% if craft.config.devMode %}DEV MODE - {% endif %}
            {{ pageTitle ?: craft.request.lastSegment()|replace({'-':' '})|title }} - {{ siteName }}
        <meta name="description" content="{{ metaDescription ?: '' }}"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        {% if craft.config.devMode %}
            <meta name="robots" content="noindex"/>
        {% endif %}
        <meta property="og:url" content="{{ craft.request.getUrl() }}"/>
        <meta property="og:site_name" content="{{ siteName }}"/>
        <meta property="og:title" content="{{ pageTitle ?: craft.request.lastSegment()|replace({'-':' '})|title }}"/>
        <meta property="og:image" content="{{ pageImage ?: '/assets/images/og-image.png' }}"/>
        <meta property="og:image:secure_url" content="{{ pageImage ?: siteUrl ~ 'assets/images/og-image.png' }}"/>
        <link rel="stylesheet" href="/assets/css/style.min.{{ craft.config.devMode ? '' : craft.config.assetVersionNum ~ '.' }}css"/>

There’s a lot going on so let me break it down a bit, starting with line 7. In my Craft config.php I like to set a devMode variable depending on the environment (local, stage, production). You are using multi-environment configs right? So on line 7 I’m adding “DEV MODE” to my <title> when in Dev Mode, so it’s obvious to me and the client when viewing the front end that we’re looking at a development version. You could also use this condition to add a class to <body> for a nice under construction-type stripy border on every page, like the Craft control panel does when in Dev Mode.

Ternary Operators

On line 8 I’m constructing our full <title> based on what is (or isn’t) passed to this template. I could’ve used standard conditional statements here but it would get a bit verbose. Instead I’m using Twig’s ternary operator syntax, which is a nice way of shortening these conditions. It works like this: In my entry template I’m setting some variables:

{% set pageTitle = entry.pageTitle %}
{% set metaDescription = entry.metaDescription %}
{% set pageImage = entry.image.first %}

Now my ternary on line 8 can check for a pageTitle. If no value is available it falls back to the last segment of our URL (craft.request.lastSegment), which is normally our entry URL right? Okay, but what if our last segment is something like “ternary-operators-rule”? Not very good for a <title>. So we need to replace the dashes with spaces and change everything to Title Case. Luckily Twig has fiters for that which we just append to our segment request (|replace({'-':' '})|title). Finally we just add on the {{ siteName }} variable. We’ll end up with something like “DEV MODE – Ternary Operators Rule – My Site”.

It gets a bit easier now on line 10. Remember the metaDescription variable we set a moment ago? Well here’s another ternary operator to output that value, or fall back to whatever you want (nothing in this case).

Line 12 adds a noindex meta when in Dev Mode so search engines don’t accidentally index the site.

Lines 15-19 add some Open Graph protocol stuff for social media. We can use our ternary operator again for the page title, and we’ll use the pageImage variable we set earlier for the og:image, or fall back to a… well, fallback image.

Last but not least, I like to use filename cache busting to cache static assets like stylesheets and Javascripts to speed up the front end – but only on the production site. Cacheing static assets during development often means your clients have to hard refresh all the time to see style changes to the site. So on line 20, when not in Dev Mode I append a version number, which comes from a variable assetVersionNum in my Craft config.php. Couple this with the following rewrite rule in your .htaccess and your filename cache busting is all set:

<IfModule mod_rewrite.c>
    RewriteEngine On
    # Filename cache busting
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.+)\.(\d+)\.(bmp|css|cur|gif|ico|jpe?g|js|png|svgz?|webp|webmanifest)$ $1.$3 [L]

Similarly you can add the assetVersionNum to your script tags too, to cache on production.

That’s about it. I’m not sure if you’d call this <head> template a macro or a module or what, and I don’t suppose it matters much. What I like about things like this is you build them right once, and they’ll handle pretty much anything that’s thrown into them. And you can use them time and again on every project. Hope it helps!