• Français
CONTACT

Hi,

Here's a tutorial about using WordPress "hooks" to insert builder layouts into the Divi header. For since Divi 3.1 (special developper edition), Elegant Themes added a few useful hooks in Divi source code.

These hooks are very powerful because they allow you to dynamically replace or add some PHP code at specific places, without having to edit the template files like header.php, and thus, without worrying about futur Divi updates.

Divi header hooks

Since we're talking about header, let's check out the header.php file in the Divi root directory. You can find there three very interesting hooks...

1. Top bar filter hook

/**
 * Filters the HTML output for the top header.
 *
 * @since ??
 *
 * @param string $top_header
 */
echo apply_filters( 'et_html_top_header', $top_header );

A "filter" hook allows us to filter a character string. In this case, the string contains the generated HTML code for the Divi top bar (the one that displays phone number, email address and secondary menu).

To be honest, I really don't like this top bar, so I usually redesign it with CSS. Now we can do better: we're going to replace it with a custom builder layout that we have previously saved in the Divi library.

Note that this filter hook is only applicable to default, centered or inline centered menus.

2. Navigation bar filter hook (including logo)

/**
 * Filters the HTML output for the main header.
 *
 * @since ??
 *
 * @param string $main_header
 */
echo apply_filters( 'et_html_main_header', $main_header );

Same kind of hook, but this one is applied on the header menu's generated HTML code, including the logo container, be it centered above the menu or not.

I won't use this filter today for I want to keep the main menu as is, but the principle is the same as the previous hook.

Again, this filter hook is only applicable to default, centered or inline centered menus.

3. Before content action hook

/**
 * Fires after the header, before the main content is output.
 *
 * @since ??
 */
do_action( 'et_before_main_content' );

A "action" hook acts like a filter, except that it adds an executable code at the specified place, instead of replacing a string. Here, it is just before the main content, below the main menu.

Header modification with hooks

This header customisation is divided in two parts:

  • layout injection replacing the top bar,
  • layout injection below the main menu bar, before the page content.

I won't replace the menu bar itself, but I hide the logo with the Customizer option. The logo will be added to the top header layout.

Top bar replacement

Requirements : The filter cannot be used unless the topbar is activated. The easiest way to achieve that is to display the social networks icons in the theme customizer (Header). Don't worry, the whole top bar will be replaced by your top header.

First, we have to design our top header with the builder and save it to the Divi Library. For instance:

Divi header builder top

Back to the library page, we can check the layout's informations ("Quick edit"):

Divi header builder top infos

The filter can now be added to the hook, using the add_filter() WordPress API function. It will replace the whole top bar's generated code with our builder layout's code, with the help of the do_shortcode() function.

Note for developpers: In general a filter can execute any kind of change with different substitutions on the string passed as a parameter of fonction add_filter(), but here we just replace everything! We don't even need the parameter.

Add this code to your child theme's functions.php file:

/* Top bar replacement */
add_filter( 'et_html_top_header', 'top_header_layout' );
function top_header_layout() {
  $query = new WP_Query( array(
    'post_type' => 'et_pb_layout',
    'post_name__in' => array('top-header')
  ));
  return do_shortcode('[et_pb_section global_module="' . $query->posts[0]->ID . '"]
                       [/et_pb_section]');
}

This code performs a database search using the layout slug to fetch the layout's WordPress post ID so that we don't have to manually look for it on each site (see above screenshot).

Layout injection below the main menu bar

Like for the top bar, we first create the layout. Here it will be a full screen section with custom menu:

Header Builder Bottom

The "Quick edit" link on the library page shows:

Header Builder Bottom infos

This time, we'll use the add_action() function to insert the code below the menu.

Add this code to your child theme's functions.php file:

/* Below menu injection */
add_action( 'et_before_main_content', 'before_content_layout' );
function before_content_layout() {
  $query = new WP_Query( array(
    'post_type' => 'et_pb_layout',
    'post_name__in' => array('after-menu')
  ));
  echo do_shortcode('[et_pb_section global_module="' . $query->posts[0]->ID . '"]
                     [/et_pb_section]');
}

Note for developpers: As you can see, the action function doesn't return a string like the previous one. We're actually using an executable code here, and the echo function directly writes the result of the shortcode function to the generated HTML file.

Plugin version

If you need to use a plugin instead of a child theme, just add a dedicated header to the previous codes and save the file to divi-builder-header.php:

<?php
/**
 * Plugin Name: Divi Builder Header
 * Plugin URI: https://pavenum.com/blog/
 * Description: Divi page header customisation.
 * Version: 1.0
 * Author: Yan Thiaudière
 * Author URI: https://pavenum.com
 * License: Free
 */

/* Top bar replacement */
add_filter( 'et_html_top_header', 'top_header_layout' );
function top_header_layout() {
  $query = new WP_Query( array(
    'post_type' => 'et_pb_layout',
    'post_name__in' => array('top-header')
  ));
  return do_shortcode('[et_pb_section global_module="' . $query->posts[0]->ID . '"]
                       [/et_pb_section]');
}

/* Below menu injection */
add_action( 'et_before_main_content', 'before_content_layout' );
function before_content_layout() {
  $query = new WP_Query( array(
    'post_type' => 'et_pb_layout',
    'post_name__in' => array('after-menu')
  ));
  echo do_shortcode('[et_pb_section global_module="' . $query->posts[0]->ID . '"]
                     [/et_pb_section]');
}

Then you just have to "zip" it and your plugin is ready.

Alternate code for performance freaks

As I wrote before, I perform a database search to get the layout internal ID... There are two reasons for this:

  • for commodity, for I can use these pieces of code wherever I want, regardless of the WordPress installation;
  • it's mandatory for the plugin version, because the plugin can't know the ID in advance!

Nevertheless, if you want to optimize page load speed with the child theme version, by skipping this database search, you can directly use the layout's internal ID, which is displayed in the URL bar of the layout edit page.

Then the code is, with ID = 999999:

/* Top bar replacement */
add_filter( 'et_html_top_header', 'top_header_layout' );
function top_header_layout() {
  return do_shortcode('[et_pb_section global_module=99999][/et_pb_section]');
}

and

/* Below menu injection */
add_action( 'et_before_main_content', 'before_content_layout' );
function before_content_layout() {
  echo do_shortcode('[et_pb_section global_module=99999][/et_pb_section]');
}

Fixed header

If you're using a fixed navigation bar, you can see that the injected layout is displayed after the main menu, and that it scrolls with the rest of the page.

To fix this, you need to add CSS '#top-header' identifier to the section div.

Note: But then you'll probably have to add a bit of CSS to design your text, because top bar CSS rules are triggered (mainly text size and line height).

Conclusion

As you can see, Divi customisation is becoming fun and easy with the addition of WordPress hooks into the code.

And there's more to come with this Elegant Themes publication about dynamic content.

Meanwhile, happy "hooking", and get your layouts ready for a futur Visual Header!

12 comments on this post

  1. Hey,
    I really like your article but wasn't able to get my divi library layout to display above the menu using the above header filter.

    I am using a child theme but don't have a copy of header.php in the child theme folder. I did open the header.php file in the divi folder and could see where each of the 3 hooks are.

    Do you know of any way for me to troubleshoot this? I really like this idea of using hooks.

    thanks for taking the time to write this article.

    John.

    1. Hi John,
      You don't need a header.php file in your child theme, you just have to add the code snippet to your child theme's functions.php file.
      Can you tell me exactly what you did and where? It's a bit hard to help you if I don't know what is wrong.

  2. Hallo,
    the above header filter is not working.
    Below filter is working.(DiviVersion: 3.11)
    Is your code correct?
    Thank you.

    1. Hi,
      Can you tell me how it is not working exactly, please ?
      Do you have an error message in the Java console ?
      Is there something displayed instead of the injected layout ?
      I copy/pasted the code on a test website with Divi 3.11 and it's still perfectly working for me.

  3. Hey, thanks for sharing this code, it's very nifty and helpful when a client wants something really unique at the top of the site that doesn't translate to a standard type of header. As you are certainly aware by now that no good deed goes unpunished 😉 I have a question for you. I have successfully replaced the top header with a very basic image in place for now, followed by the primary menu navigation. Unfortunately if I make the primary nav transparent so that it can float above a slider, it forces the replacement top header area to be huge, like 500px high... Not sure where that is coming from or what I might do about it, so thought you might have an idea. Thanks again for doing this for everyone.

    1. Hi Gil,

      You're right, as soon as the header menu is NOT 100% opaque, a huge padding-top is applied to the top-header, and I don't understand why... Besides, menu is too high, hidden by the top-header section. It seems ET have not covered everything when introducing the header hooks.

      I tried to solve it manually with CSS (padding-top for top-header and page-container, top position for menu), but it's impossible because top-header height is variable (section or row padding in percentage, dynamic modules height, etc.). So we need Javascript here, and it's out of scope.

      I'll try to send ET a bug report as soon as I can.

      Thanks for letting us know, and good luck with this...
      I'm afraid you have to stick to non-sticky for now 😉

  4. Hi Yan
    is it good practice to use shortcode such as this to alter the header?

    add_action( 'et_before_main_content', 'before_content_layout' );
    function before_content_layout() {
    echo do_shortcode('[et_pb_section global_module=99999][/et_pb_section]');

    Do you use this method often on your websites?

    Is it not better to hardcode changes you want to make to the header.php file?
    thanks

    1. Hi Maria,

      The proper way to do it is using WordPress hooks, either with shortcodes or any other code.

      The purpose of hooks is precisely to inject code wherever it's possible, without modifying theme (or plugins) PHP files.

      And it is best practice for two reasons:

      First, when you directly edit PHP files, your modifications will be lost when you update WP or theme or plugin, because edited files will be replaced by their new versions (thus, without your modifications). Using hooks, your modifications are externalised and won't be lost when new files versions come.

      Second, all your modifications can be centralised in your child theme (or a plugin), so it's cleaner and more portable (you can copy your child theme to a new fresh WP install, for instance).

      I hope it makes sense! Hooks are very powerfull and themes and plugins use it more and more, which is good news.

      Have a good day,
      Yan.

  5. The top header thing for me anyway put it below the header. It didn't put it above. Did I do something wrong or does this tut not work anymore?

    1. Hi Echo,
      It should still work, but I have no time to test it at the moment.
      Also, today Divi has a lot more options to make custom headers (with theme builder), so you might not need this any longer...
      Depends on how complex is your need, I guess.

Leave a Reply

Your IP address will not be logged.
You can fill in your name or nickname if you are human ;-)