Adding Google Fonts to your WordPress theme

Image displaying Abc

Google Fonts are a great alternative to expensive font foundries like Adobe Typekit or free ones like Font Squirrel and Edge Web Fonts. Why great? In my opinion it’s mostly the amount of fonts available and their ease of use. In pure HTML pages, you just paste a bit of code that you got by choosing your font, and you’re all set. Simplicity is the key here.

Notice: This article was written in 2016. WordPress has changed a lot since then, so take this article with a grain of salt…

So naturally we can ask ourselves: how to use them in our WordPress themes?

When I first started working on WordPress themes the way I included them was just to enqueue the code I got from Google in my wp_enqueue_scripts hook like

wp_enqueue_style('yourtheme-google-fonts', '//fonts.googleapis.com/css?family=Open+Sans', array(), null);Code language: PHP (php)

But since then I think I’ve grown and learned the right way to do it. I’ll explain to you how to include the Google Fonts in your theme Customizer and set it all up.

Google Fonts API key and customizer

First thing you’ll need to get is a Google Fonts API key. To do that go to Google developers console and follow the instructions to get your API key. It’s super simple, you shouldn’t have any issues with that.

We need this key so that we can create a custom control in our Theme customizer. You can learn all about it in my previous posts here and here. In our customizer.php we’ll add a separate Fonts section, and in it we’ll add one setting and control.

/**
------------------------------------------------------------
SECTION: Fonts
------------------------------------------------------------
**/
$wp_customize->add_section('section_fonts', array(
	'title'		=> esc_html__('Fonts', 'mytheme'),
	'priority'	=> 0,
));

    /**
	Main Google Font Setting
	**/
    $wp_customize->add_setting( 'main_google_font_list', array(
        'default'           => '',
        'sanitize_callback' => 'sanitize_text_field',
    ));
    $wp_customize->add_control( new Google_Font_Dropdown_Custom_Control( $wp_customize, 'main_google_font_list', array(
        'label'      => 'Main Google Font',
        'section'    => 'section_fonts',
        'settings'   => 'main_google_font_list',
    )));Code language: PHP (php)

As you can see I added one setting and one control for main fonts. You could extend this to include header fonts, post fonts, footer fonts etc. Just have in mind that the more fonts you have, the more fonts you’ll load and this could impact your page performance (speed).

Next you’ll need the custom control called Google_Font_Dropdown_Custom_Control. In your custom_controls.php you’ll add

class Google_Font_Dropdown_Custom_Control extends WP_Customize_Control{
	private $fonts = false;
    public function __construct($manager, $id, $args = array(), $options = array()){
        $this->fonts = $this->get_google_fonts();
        parent::__construct( $manager, $id, $args );
    }

    public function render_content(){
        ?>
            <label class="customize_dropdown_input">
                <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
            	<select id="<?php echo esc_attr($this->id); ?>" name="<?php echo esc_attr($this->id); ?>" data-customize-setting-link="<?php echo esc_attr($this->id); ?>">
                    <?php
                        foreach ( $this->fonts as $k => $v ){
                            echo '<option value="'.$v['family'].'" ' . selected( $this->value(), $v['family'], false ) . '>'.$v['family'].'</option>';
                        }
                    ?>
                </select>
            </label>
        <?php
    }

	public function get_google_fonts(){
		if (get_transient('mytheme_google_font_list')) {
        	$content = get_transient('mytheme_google_font_list');
	    } else {
	        $googleApi = 'https://www.googleapis.com/webfonts/v1/webfonts?sort=alpha&key=AIzaSyD9cCtZWra_aNI4y4krjYpT4Id2PaP_Skg';
	        $fontContent = wp_remote_get( $googleApi, array('sslverify'   => false) );
	        $content = json_decode($fontContent['body'], true);
	        set_transient( 'mytheme_google_font_list', $content, 0 );
	    }

	    return $content['items'];
	}

}Code language: JavaScript (javascript)

First you create a constructor that will get all the fonts from Google Fonts API. In the get_google_fonts() function you’ll store the fonts in a transient. Transients are a great way to store the data in the database for certain amount of time. In our case it’s 0 so it never expires, because we assume that fonts don’t get added to the google font list that often. But here you could set the expiration of transient to several months if you wish. Now if transient exists you’ll pull the data from it, but if it doesn’t (which it won’t on your first run) you need to create it.

The $googleApi variable contains the link to the google fonts with your key you created earlier – here it’s AIzaSyD9cCtZWra_aNI4y4krjYpT4Id2PaP_Skg, in your case it will be something different of course. Just paste your key here and it should work. Next you are fetching the content using wp_remote_get() function, and you are decoding the JSON response you got from it.

In the render_content() function we just created a simple HTML select with the list of our Google Fonts.

Google Fonts in Customizer
Google Fonts in Customizer

Great, we have our fonts in the customizer, now we need to enqueue them in our theme.

Enqueuing the fonts

To make our fonts available in our theme we need to enqueue them properly. Inside the wp_enqueue_scripts hook add

wp_enqueue_style('yourtheme-google-fonts', yourtheme_fonts_url(), array(), null);

Next thing you need is the aforementioned function so below in your functions.php just add

/********* Google Fonts URL function  ***********/
if ( ! function_exists( 'yourtheme_fonts_url' ) ){
	function yourtheme_fonts_url() {
	    $fonts_url = '';
	    $content_font = get_theme_mod('main_google_font_list', '');
	    // Translators: If there are characters in your language that are not supported by Google font, translate it to 'off'. Do not translate into your own language.
	    // $content_font = _x( 'on', ''.$content_font.' font: on or off', 'yourtheme' );


	    if ( 'off' !== $content_font ) {
	        $font_families = array();

	        if ( 'off' !== $content_font ) {
	            $font_families[] = $content_font;
	        }

	        $query_args = array(
	            'family' => urlencode( implode( '|', array_unique($font_families) ) ),
	        );

	        $fonts_url = add_query_arg( $query_args, 'https://fonts.googleapis.com/css' );
	    }

	    return esc_url_raw( $fonts_url );
	}
}Code language: PHP (php)

If you created more settings, just add them in a variable like $content_font , and add them in the if condition like this for instance

/********* Google Fonts URL function  ***********/
if ( ! function_exists( 'yourtheme_fonts_url' ) ){
	function yourtheme_fonts_url() {
	    $fonts_url = '';
	    $content_font = get_theme_mod('main_google_font_list', '');
	    $header_font = get_theme_mod('header_google_font_list', '');
	    // Translators: If there are characters in your language that are not supported by Google font, translate it to 'off'. Do not translate into your own language.
	    // $content_font = _x( 'on', ''.$content_font.' font: on or off', 'yourtheme' );
	    // $header_font = _x( 'on', ''.$header_font.' font: on or off', 'yourtheme' );

	    if ( 'off' !== $content_font || 'off' !== $header_font ) {
	        $font_families = array();

	        if ( 'off' !== $content_font ) {
	            $font_families[] = $content_font;
	        }

	        if ( 'off' !== $header_font ) {
	            $font_families[] = $header_font;
	        }

	        $query_args = array(
	            'family' => urlencode( implode( '|', array_unique($font_families) ) ),
	        );

	        $fonts_url = add_query_arg( $query_args, 'https://fonts.googleapis.com/css' );
	    }

	    return esc_url_raw( $fonts_url );
	}
}Code language: PHP (php)

And that’s it. You’ll have all the fonts loaded in your theme, and you can use it in your CSS as you wish.

Hope this code will be helpful, if you have any questions or comments just use the comment section below. Happy coding!

21 responses

  1. Thanks sir

  2. Undefined index: items in C:\xampp\htdocs\wordpress6\wp-content\themes\spicyaroma\inc\customizer.php on line 225. Error in following code and sir can you explain ?mytheme_google_font_list
    fonts = $this->get_google_fonts();
    parent::__construct( $manager, $id, $args );
    }

    public function render_content(){
    ?>

    label ); ?>
    <select id="id); ?>” name=”id); ?>” data-customize-setting-link=”id); ?>”>
    fonts as $k => $v ){
    echo ‘value(), $v[‘family’], false ) . ‘>’.$v[‘family’].”;
    }
    ?>

    false) );
    $content = json_decode($fontContent[‘body’], true);
    set_transient( ‘mytheme_google_font_list’, $content, 0 );
    }

    return $content[‘items’];
    }

    }

    1. Looks like the $fontContent['body'] is not set, so the $content array doesn’t contain the 'items' key. Why that is, it’s hard to say. Try debugging the code a bit.

  3. I have an Error notice:
    Undefined index: items in C:\xampp\htdocs\wordpress6\wp-content\themes\spicyaroma\inc\customizer.php on line 225.
    can you find which type of error occurring

    1. It’s hard to guess what could be the issue without a code example. Try adding a check if the items index exists before using it.

  4. Nice post! Very helpful!

  5. Shwan Namiq Avatar
    Shwan Namiq

    Thank you so much this article helped me a lot of to setting transient to my google font api within my plugin

    1. Glad I could help :)

  6. Bro one more problem is when i choose two font then it output it as https://fonts.googleapis.com/css?family=Cookie%7C%7CAlef thats why fonts not working.

  7. Rakib Khan Avatar
    Rakib Khan

    Please can you tell me what is the mistake in my code as i am getting syntax error unexpected eof msg!
    Here is my code – /********* Google Fonts URL function ***********/
    if ( ! function_exists( ‘rk_fonts_url’ ) ){
    function rk_fonts_url() {
    $fonts_url = ”;
    $logo_font = get_theme_mod(‘rk_logo_font’, ”);
    $headlines_font = get_theme_mod(‘rk_headlines_font’, ”);
    $titles_font = get_theme_mod(‘rk_titles_font’, ”);
    $texts_font = get_theme_mod(‘rk_texts_font’, ”);
    $links_font = get_theme_mod(‘rk_links_font’, ”);
    $navs_font = get_theme_mod(‘rk_navs_font’, ”);
    // Translators: If there are characters in your language that are not supported by Google font, translate it to ‘off’. Do not translate into your own language.
    // $logo_font = _x( ‘on’, ”.$logo_font.’ font: on or off’, ‘rk’ );
    // $headlines_font = _x( ‘on’, ”.$headlines_font.’ font: on or off’, ‘rk’ );
    // $titles_font = _x( ‘on’, ”.$titles_font.’ font: on or off’, ‘rk’ );
    // $texts_font = _x( ‘on’, ”.$texts_font.’ font: on or off’, ‘rk’ );
    // $links_font = _x( ‘on’, ”.$links_font.’ font: on or off’, ‘rk’ );
    // $navs_font = _x( ‘on’, ”.$navs_font.’ font: on or off’, ‘rk’ );

    if ( ‘off’ !== $logo_font || ‘off’ !== $headlines_font || ‘off’ !== $titles_font || ‘off’ !== $texts_font || ‘off’ !== $links_font || ‘off’ !== $navs_font ) {
    $font_families = array();

    if ( ‘off’ !== $logo_font ) {
    $font_families[] = $logo_font;
    }

    if ( ‘off’ !== $headlines_font ) {
    $font_families[] = $headlines_font;

    if ( ‘off’ !== $titles_font ) {
    $font_families[] = $titles_font;
    }

    if ( ‘off’ !== $texts_font ) {
    $font_families[] = $texts_font;

    if ( ‘off’ !== $links_font ) {
    $font_families[] = $links_font;
    }

    if ( ‘off’ !== $navs_font ) {
    $font_families[] = $navs_font;
    }

    $query_args = array(
    ‘family’ => urlencode( implode( ‘|’, array_unique($font_families) ) ),
    );

    $fonts_url = add_query_arg( $query_args, ‘https://fonts.googleapis.com/css’ );
    }

    return esc_url_raw( $fonts_url );
    }
    }

    1. You are missing several of the closing } braces in your conditionals. In the future I recommend you use StackOverflow to ask these kind of questions, the code can be viewed much clearer there :)

      1. thanks bro, i did solve it!

  8. Kandyce Clark Avatar
    Kandyce Clark

    is it possible to add font weight and other font attributes to the customizer because i had followed another tutorial and for some reason i keep getting the error message : invalid value or something of that nature and i am usually pretty good with fixing my errors but i cannot figure out what ive done wrong

    1. You could but it’s not sure that it will work as you intend. Not every google font supports every font weight. If you use postman app, and type in https://www.googleapis.com/webfonts/v1/webfonts?sort=alpha&key={your api key here} you’ll see a json response, with all fonts. Some have `variants` as numbers, some as italic and regular. It depends.

      I’d suggest using Easy Google Fonts plugin. It’s awesome for customizing fonts on your page :) Sometimes plugins are the way to go :D

      1. Kandyce Clark Avatar
        Kandyce Clark

        I’ve actually found a way to do this! You would add the font weight option as normal in the customize.php file then add a sanitizer for it and it worked like a charm. I was able to add font weight, and letter spacing options to the customizer

  9. Georgia Lou Studios Avatar
    Georgia Lou Studios

    Thank you for this. It works brilliantly, except, when it outputs the css link in the head, I’m getting 2 “|” in the googleapis.com link instead of one between each font when you try to use multiple theme mods. Like this:

    https://fonts.googleapis.com/css?family=Caesar+Dressing%7C%7CMontserrat

    %7C%7C translates to || instead of just | between the font family names. So of course then the fonts don’t work at all.

    And when I try to edit this line and remove the “|” of course it removes both:

    family’ => urlencode( implode( ‘|’, array_unique($font_families) ) ),

    Any idea what’s going on with this?

    1. Georgia Lou Studios Avatar
      Georgia Lou Studios

      Never mind. It’s working properly now. Not sure what it was doing then but it’s working great now. Thanks again for a fantastic snippet!

      1. Not sure why that happened, glad you got it working :)

        1. Georgia Lou Studios Avatar
          Georgia Lou Studios

          Hello –

          Unfortunately, I am having the same problem again. I believe I have isolated WHEN it is happening.

          I have multiple font options in the Customizer. If the same font is chosen more than once then the font family is added to the Google Fonts URL with the double || (%7C%7C) rather than the single |.

          This breaks the URL and the fonts don’t load.

          If all the font options are set to totally different fonts, this doesn’t happen.

          Any idea how to fix this?

          Thanks in advance!

          1. I tested it in my twentysixteen theme and the only thing that is faulty (which I have now fixed in the code above) was the fact that I placed the fonts to the $font_families array in the wrong way (I used $font_families[] .= ''.$content_font.''; instead of $font_families[] = $content_font;). Try fixing this. I tested it and it should work – I added main font, footer and header and I put header and main to the same font, and footer to some other and only 2 of them were placed in the array.

            I realize that I should add font weight and family subset to the mix, but that would kinda complicated things a bit. I’d need to modify the code a bit…

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.