Show Similar Post Titles ( Similar to Stack Exchange )

I really like how Stack Exchange sites handle posts, where after you finish typing the title it will list out similar titles. How can I implement something similar on my WordPress installation?

The reason being is that hopefully it will show duplicate titles at the top, so that I do not accidently publish a post with the same title as an older post.

Related posts

Leave a Reply

1 comment

  1. This will get you most of the way there, but the actual search is not perfect. It would be great if someone who knows more about $wpdb can help get a better result.

    If this is my original post title: SOPA is dead, woot!

    Then just a title of “SOPA” will find it, as will just a title of “is dead” but not “Ding dong, the witch is dead” or “SOPA is a bad idea”.

    However, the basic premise is a button is added to “Check Title”, and when pressed, the title is posted with jQuery and handled via AJAX to return matching titles, excluding the current post. If you are able to take this and modify it to return better matches, please share!

    Here is the base plugin code, followed by the jQuery which should be included in your plugin folder in a file called duptitles.js

    /*
    Plugin Name: Duplicate Titles Check
    Description: Prevent user's using similar post titles.
    Version: 1.0
    Author: 5t3ph
    Author URI: http://stephscharf.me
    */
    
    //jQuery to send AJAX request - only available on the post editing page
    function dup_titles_enqueue_scripts( $hook ) {
    
        if( !in_array( $hook, array( 'post.php', 'post-new.php' ) ) )
            return;
    
        wp_enqueue_script( 
            'duptitles',
            plugins_url( '/duptitles.js', __FILE__ ),
            array( 'jquery' )
        );
    }
    add_action( 'admin_enqueue_scripts', 'dup_titles_enqueue_scripts', 2000 );
    
    
    // Invoke baked-in WP ajax goodness
    // Codex: http://codex.wordpress.org/AJAX_in_Plugins
    add_action('wp_ajax_title_check', 'title_check_callback');
    
    function title_check_callback() {
    
        function title_check() {
    
            $title = $_POST['post_title'];
            $post_id = $_POST['post_id'];
    
            global $wpdb;
    
            $sim_titles = "SELECT post_title 
                        FROM $wpdb->posts 
                        WHERE post_status = 'publish' AND post_type = 'post' 
                        AND post_title LIKE '%{$title}%' 
                        AND ID != {$post_id}";
    
            $sim_results = $wpdb->get_results($sim_titles);
    
            if($sim_results) {
                $titles = '<ul>';
                foreach ( $sim_results as $the_title ) 
                {
                    $titles .= '<li>'.$the_title->post_title.'</li>';
                }
                $titles .= '</ul>';
    
                return $titles;
            } else {
                return '<p>This title is unique</p>';
            }
        }
    
        echo title_check();
    
        die();
    }
    

    Begin jQuery for duptitles.js

    jQuery(document).ready(function($){
        // Post function
        function checkTitle(title, id) {
            var data = {
                action: 'title_check',
                post_title: title,
                post_id: id
            };
    
            //var ajaxurl = 'wp-admin/admin-ajax.php';
            $.post(ajaxurl, data, function(response) {
                $('#message').remove();
                $('#poststuff').prepend('<div id="message" class="updated fade"><p>'+response+'</p></div>');
            }); 
        };
    
        // Add button to "Check Titles" below title field in post editor
        $('#edit-slug-box').append('<span id="check-title-btn"><a class="button" href="#">Check Title</a></span>');
    
        // Click function to initiate post function
        $('#check-title-btn a').click(function() {
            var title = $('#title').val();
            var id = $('#post_ID').val();
            checkTitle(title, id);
        });
    
    });