Adding blocks to the head section in Magento 2

As we all know, the page’s HTML <head> section contains different meta tags, CSS and JS files definition, pieces of JS code etc. As a rule, we don’t need any complex logic to add some proper content there. However, let’s imagine the situation when we need to insert some element that depends on the system configuration or so into the head section.

After years of development on Magento 1 this operation might be a bit tricky in the newest Magento version. Below we will present “How to” for adding blocks and templates to the head section.

If you worked (or still work) with Magento 1, you should know that it’s quite easy to operate with contents of the head section. There’s almost no difference between blocks in the head section and blocks in the body section. In the layout structure we have the following block that contains all head’s contents:

<block type="page/html_head" name="head" as="head">
    ...
</block>

So, to add some child block to this section we just need to insert it to the corresponding reference:

<reference name="head" before="-">
    <block type="googleanalytics/ga" name="google_analytics" as="google_analytics" template="googleanalytics/ga.phtml" />
</reference>

That’s all, we can insert any child block using the described approach in Magento 1.

In Magento 2 the layout structure is different. The page’s layout is defined by the theme’s layout configuration file – “[Magento_Theme_module_dir]/view/frontend/layout/default.xml”. If you check this file, the name of the root node now is <page>. It contains two main sections: <head> and <body>. It’s very handy structure since we don’t have a pack of blocks directly inside of the root node anymore but have the separated two main parts with the corresponding elements. Obviously, to add a child block to the new <head> section we need to insert it to this section. But do not hurry up with your conclusions. We don’t have a simple ability to insert a child block directly to the <head> section anymore in Magento 2. There we can only operate with a page title or add static files and meta tags as in the example below:

<head>
    <title>Review Order</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
    <attribute name="prefix" value="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# product: http://ogp.me/ns/product#" />
    <css src="jquery/fileUploader/css/jquery.fileupload-ui.css"/>
    <link src="Magento_Customer::js/bootstrap/customer-post-action.js"/>
</head>

But, on attempt to insert some block you will not see its contents since blocks are not allowed in this section. In order to insert a block you need to use an intermediate reference container, but where can we find it? If you check the “[Magento_Theme_module_dir]/view/frontend/layout/default.xml” layout file once again, at the very bottom you will find an interesting block called “head.additional”. It’s really surprising place, isn’t it?

Upon a page’s rendering process the \Magento\Framework\View\Result\Page::render method gets its block contents and inserts into the HTML <head> section. As the result, we can use this block as a reference to insert an additional section block:

<body>
    <referenceBlock name="head.additional">
        <block class="Atwix\Helloworld\Block\TestBlock" name="atwix_testblock" template="test_block.phtml"/>
    </referenceBlock>
</body>

Please note, we need to use the <head> node as a parent here since the “head.additional” block is originally placed inside of this section.

It might seem like Magento 2 is much more complex and non-intuitive. However, such complexity brings more order and cleanness into the code, so be patient and you will like it. We hope that the described approach will save you some time in attempts to add a child block to the head section. Feel free to share your findings and ask questions in the comments below. And, remember, Magento 2 isn’t difficult and that’s a real fun to find something new there again and again.

Read more: