Adding a “You might also like” overlay to another WordPress post using scroll events

How do you encourage users to stay on your site and how do you let them know about the rest of the great content you have on your site? If a user has read or is reading and article on your site, they may like to know about similar content. You could have a series of thumbnails or related articles, but why not give a specific post a little more priority?

In this tutorial we’ll be using jQuery to detect when the user has scrolled to or near the bottom of the article. Once they are near it, we’ll display a small overlay in the bottom right, with a suggestion for a related post they may find interesting.

Getting Started

First we’ll need to register our function within WordPress using the add_action function and wp_footer action

function theme_append_similar_to_footer() {
}
add_action('wp_footer', 'theme_append_similar_to_footer');

Using this action, anything we output will be appended to the footer of the page, before the closing body tag. We don’t want to output our “You might also like” overlay on every post within the site, so using the built in WordPress conditional function is_single() we can limit it to only individual posts

function theme_append_similar_to_footer() {
    if ( is_single() ) {
    }
}
add_action('wp_footer', 'theme_append_similar_to_footer');

Getting the current post tags or categories

To actually find a post that is similar to the current one, we can use tags or categories. To do this we can use wp_get_post_tags and wp_get_post_categories, to specify that we only want the IDs we just specify the field value in the function parameters.

To actually get a post, we use WP_Query, passing in our order by, the categories/tags (category__in and tag__in) that we want and the fact that we only want 1 result (posts_per_page). We also make sure to exclude the current post by using post__not_in


function theme_append_similar_to_footer() {
    if ( is_single() ) {
        global $post;
        $tags = wp_get_post_tags($post->ID, array( 'fields' => 'ids' ));
        $categories = false;
        
        if(!$tags) {
            $categories = wp_get_post_categories($post->ID, array( 'fields' => 'ids' ));
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'category__in' => $categories,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        } else {
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'tag__in' => $tags,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        }       
    }
}
add_action('wp_footer', 'theme_append_similar_to_footer');

Here I’m using tags, and then if there are no tags falling back to categories. You could of course mix it up and pick specific ones or perhaps limit the query to stickied posts.

Next up we have to output the HTML we want to appear.

function theme_append_similar_to_footer() {
    if ( is_single() ) {
        global $post;
        $tags = wp_get_post_tags($post->ID, array( 'fields' => 'ids' ));
        $categories = false;
        
        if(!$tags) {
            $categories = wp_get_post_categories($post->ID, array( 'fields' => 'ids' ));
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'category__in' => $categories,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        } else {
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'tag__in' => $tags,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        }
            
        if( $similar_query->have_posts() ) {
            while ($similar_query->have_posts()) { 
                $similar = $similar_query->the_post(); 
                ?> 
                <aside class="you-may-like">    
                    <header>
                        <h2>You might also like... </h2>
                        <h2><a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
                        <?php the_post_thumbnail('thumbnail'); ?>
                    </header>
                    <?php the_excerpt(); ?>
                </aside>                
                <?php
            }             
        }            
        wp_reset_postdata();
    }
}
add_action('wp_footer', 'theme_append_similar_to_footer');

no-css

Styling our “You might also like” overlay

To style the overlay, we’re going to first set its position to fixed so that it’s scrolls with the user. We’re then going to position it to the bottom right of the screen. We’ll also need to give it a background color, here I’m using a semi-transparent background. To make everything feel a bit neater and easier to read, we should specify some padding and a fixed with. Once you’re happy with with your styling, we need to set its display attribute to none and hide it. Later using jQuery we’ll make it visible when the user scrolls to the end of the article.

aside.you-may-like {
    position: fixed;
    bottom: 2em;
    right: 0px;
    text-decoration: none;
    color: #000000;
    background-color: #EBEBEB;
    background-color: rgba(235, 235, 235, 0.8051);
    font-size: 12px;
    padding: 20px;
    display: none;
    width: 300px;
}

aside.you-may-like h2{
    margin: 0px 0px 20px 0px;
}

aside.you-may-like p{
    line-height: 150%;
}

with-css

Dynamically showing our “You might also like” overlay

To actually calculate when we should display our overlay, we need to get the outerHeight of the the article. We use the outerHeight property because it includes all of the padding, border and margin (if you pass in true) values. It is essentially the ‘true’ height of a HTML element. We then need to get the innerHeight of the window. The inner height is the size of an element excluding the padding, border and margin values. Finally we need to get the current position of the scroll bar, to do this we use the jQuery scrollTop function. To trigger the “You might also like” overlay early, I’m also going to specify an offset of 200 pixels.

We use the above values to calculate how close we are to the end. We need to do this every time the user scrolls. To achieve this we use the jQuery scroll function. To actually show and it, I’m using the fadeIn and fadeOut functions, you could use any of the other built in jQuery effects or create your own using the animate function

jQuery(document).ready(function() {
    var article = jQuery('article.post');
    var aside = jQuery('aside.you-may-like');
    var offset = 200;
    jQuery(window).scroll(function() {
        var outerHeight = article.outerHeight(true);
        var height = jQuery(window).innerHeight();
        var top = jQuery(window).scrollTop();
                                    
        if( ( height + top ) >= ( outerHeight - offset )) {
            aside.fadeIn(200);                        
        } else {
            aside.fadeOut(200);
        }                    
    });            
});

I’ve included the script and style elements of this tutorial inside the theme_append_similar_to_footer function. You could have them attached separately and add them to the page using the wp_enqueue_style and wp_enqueue_script functions


function theme_append_similar_to_footer() {
    if ( is_single() ) {
        global $post;
        $tags = wp_get_post_tags($post->ID, array( 'fields' => 'ids' ));
        $categories = false;
        
        if(!$tags) {
            $categories = wp_get_post_categories($post->ID, array( 'fields' => 'ids' ));
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'category__in' => $categories,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        } else {
            $similar_query = new WP_Query( array( 
                'orderby' => 'date', 
                'tag__in' => $tags,
                'post__not_in' => array($post->ID),
                'posts_per_page' => '1'
            ) );
        }
            
        if( $similar_query->have_posts() ) {
            while ($similar_query->have_posts()) { 
                $similar = $similar_query->the_post(); 
                ?> 
                <aside class="you-may-like">    
                    <header>
                        <h2>You might also like... </h2>
                        <h2><a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
                        <?php the_post_thumbnail('thumbnail'); ?>
                    </header>
                    <?php the_excerpt(); ?>
                </aside>
                <style>
                    aside.you-may-like {
                        position: fixed;
                        bottom: 2em;
                        right: 0px;
                        text-decoration: none;
                        color: #000000;
                        background-color: #EBEBEB;
                        background-color: rgba(235, 235, 235, 0.8051);
                        font-size: 12px;
                        padding: 20px;                        
                        width: 300px;
                        display: none;
                    }

                    aside.you-may-like h2{
                        margin: 0px 0px 20px 0px;
                    }
                    
                    aside.you-may-like p{
                        line-height: 150%;
                    }
                </style>
                <script>
                    jQuery(document).ready(function() {
                        var article = jQuery('article.post');
                        var aside = jQuery('aside.you-may-like');
                        var offset = 200;
                        jQuery(window).scroll(function() {
                            var outerHeight = article.outerHeight(true);
                            var height = jQuery(window).innerHeight();
                            var top = jQuery(window).scrollTop();
                                                        
                            if( ( height + top ) >= ( outerHeight - offset )) {
                                aside.fadeIn(200);                        
                            } else {
                                aside.fadeOut(200);
                            }                    
                        });            
                    });
                </script>
                <?php
            }             
        }            
        wp_reset_postdata();
    }
}
add_action('wp_footer', 'theme_append_similar_to_footer');

Customizing this further

By default WordPress thumbnails are 150px*150px, that’s quite large for an overlay of this size. You could add a custom size to your theme using the add_image_size function. If you’re using this on a preexisting site, you may need to regenerate your existing images to create the smaller images. You can do this using the excellent Regenerate Thumbnails plugin by Alex Mills

add_image_size( 'small', 50, 50, true );

You could also add back and next actions to this, so the user can skip a post they are not interested in. To do this you can use the built in AJAX support in WordPress. I won’t cover that here as it’s a full tutorial in itself, let me know if you want me to and I’ll cover it in an upcoming tutorial.

SHARE THIS POST
  • Lam Nguyen

    Thanks so much for this.