Divi header: include builder layouts using WordPress hooks

10 May 2018

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:

Modèle d'entête Divi en bibliothèque

Back to the library page, we can check the layout’s informations (“Quick edit”):

Informations du modèle d'entête DIvi

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:

Modèle d'entête Divi en bibliothèque

The “Quick edit” link on the library page shows:
Informations du modèle d'entête DIvi

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:

Onglet avancé des paramètres de section Divi

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!