Posted on

Adding direct links to outside pages to search results

Hi, is there a way to add a link to another website when searching for certain keywords? We have a few affiliates and we want to include a direct link to their websites in the search results when certain terms are searched for. How would I go about this?

A straight-forward approach for this is to create a custom post type for the affiliate links, have Relevanssi index that post type and then instead of linking to the post, have the search results page link to the website link.

How to do that, then? Here’s how. First, we need to register the custom post type:

add_action( 'init', 'rlv_affiliate_link_post_type' );

/**
 * Register a custom post type called "affiliate_link".
 *
 * @see get_post_type_labels() for label keys.
 */
function rlv_affiliate_link_post_type() {
    $labels = array(
        'name'                  => _x( 'Affiliate links', 'Post type general name', 'textdomain' ),
        'singular_name'         => _x( 'Affiliate link', 'Post type singular name', 'textdomain' ),
        'menu_name'             => _x( 'Affiliate links', 'Admin Menu text', 'textdomain' ),
        'name_admin_bar'        => _x( 'Affiliate link', 'Add New on Toolbar', 'textdomain' ),
        'add_new'               => __( 'Add New', 'textdomain' ),
        'add_new_item'          => __( 'Add New Affiliate link', 'textdomain' ),
        'new_item'              => __( 'New Affiliate link', 'textdomain' ),
        'edit_item'             => __( 'Edit Affiliate link', 'textdomain' ),
        'view_item'             => __( 'View Affiliate link', 'textdomain' ),
        'all_items'             => __( 'All Affiliate links', 'textdomain' ),
        'search_items'          => __( 'Search Affiliate links', 'textdomain' ),
        'parent_item_colon'     => __( 'Parent Affiliate links:', 'textdomain' ),
        'not_found'             => __( 'No Affiliate links found.', 'textdomain' ),
        'not_found_in_trash'    => __( 'No Affiliate links found in Trash.', 'textdomain' ),
        'archives'              => _x( 'Affiliate link archives', 'The post type archive label used in nav menus. Default "Post Archives". Added in 4.4', 'textdomain' ),
        'filter_items_list'     => _x( 'Filter Affiliate links list', 'Screen reader text for the filter links heading on the post type listing screen. Default "Filter posts list"/"Filter pages list". Added in 4.4', 'textdomain' ),
        'items_list_navigation' => _x( 'Affiliate links list navigation', 'Screen reader text for the pagination heading on the post type listing screen. Default "Posts list navigation"/"Pages list navigation". Added in 4.4', 'textdomain' ),
        'items_list'            => _x( 'Affiliate links list', 'Screen reader text for the items list heading on the post type listing screen. Default "Posts list"/"Pages list". Added in 4.4', 'textdomain' ),
    );

    $args = array(
        'labels'              => $labels,
        'public'              => false,
        'publicly_queryable'  => false,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'query_var'           => false,
        'rewrite'             => array( 'slug' => 'affiliatelink' ),
        'capability_type'     => 'post',
        'has_archive'         => false,
        'hierarchical'        => false,
        'menu_position'       => null,
        'supports'            => array( 'title', 'editor' ),
        'exclude_from_search' => false,
    );

    register_post_type( 'affiliatelink', $args );
}

A large part of that is just the labels, but here we register a simple post type with the name affiliatelink. The post type is private and doesn’t have any archives to it. It should be fairly invisible on the site, but it does appear in the admin dashboard and in Relevanssi indexing settings and can be searched.

The way this post type is used is simple. Put the link to the site in the post title and any keywords you want the link to be found with in the post content.

Because we’re using the title field for the link, we don’t want that to be indexed by Relevanssi. Let’s stop that:

add_filter( 'relevanssi_post_title_before_tokenize', 'rlv_no_affiliate_link_titles', 10, 2 );
function rlv_no_affiliate_link_titles( $title, $_post ) {
    if ( 'affiliatelink' === $_post->post_type ) {
        $title = '';
    }
    return $title;
}

This simple function hooks to the relevanssi_post_title_before_tokenize filter hook and empties out the title of the post if the post type is affiliatelink. Now Relevanssi won’t see the title.

Now the final piece we need is a method that uses the link in the post title instead of the actual permalink of the post. This could be done on the search results template, but we can also do this with filters:

add_filter( 'post_type_link', 'rlv_affiliate_link_permalink', 10, 2 );
add_filter( 'the_permalink', 'rlv_affiliate_link_permalink', 10, 2 );

function rlv_affiliate_link_permalink( $permalink, $_post = null ) {
    if ( ! $_post ) {
        global $post;
        $_post = $post;
    } elseif ( is_int( $_post ) ) {
        $_post = get_post( $_post );
    }

    if ( 'affiliatelink' === $_post->post_type ) {
        return $_post->post_title;
    }

    return $permalink;
}

The post_type_link covers get_permalink() and the_permalink handles the_permalink(). This function replaces the post permalink with the post title, if the post type is affiliatelink.

That’s almost all we need. The rest is up to the theme: you probably want to style these results differently in the search results template. For example, there’s no point showing an excerpt for these results. That’s something you need to handle on the search results template. You can check for the post type and use a different subtemplate for these posts.

Leave a Reply

Are you a Relevanssi Premium customer looking for support? Please use the Premium support form.

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.