Skip to content

Custom Attributes

Michael Beckwith edited this page Dec 13, 2022 · 6 revisions

Discover how to push your custom attributes and adapt your Algolia ranking settings.

Introduction

By default, the plugin indexes some attributes for each content type. The complete list can be found in the Index Schema documentation.

Sometimes you may want to push additional attributes.

To illustrate the many concepts involved in building a search based on custom data, let us guide you through a concrete example.

Page Visits Matter!

Example: We want to consider the page visits count in the ranking formula for all post types.

In this example we will show you:

  • How to bootstrap a plugin,
  • A very naive way of counting page visits and keep track of a counter per post,
  • How to append the post visits count to the data pushed to Algolia,
  • How to override the default Ranking Formula to take into account the visits counter,
  • How to secure the sensitive data,
  • How to queue a re-indexing tasks at a given interval,

Bootstrap A New Plugin

Let's say that our plugin is called "Visits Matter".

Create your plugin file ./wp-content/plugins/visitsmatter.php with the following content:

<?php
/*
Plugin Name: Visits Matter
*/

Head to your WordPress admin panel and go enable your newly created plugin.

Count Page Visits


This is a very trivial way of counting visits, do not use this implementation on a production website which has a lot of traffic.


Here is our plugin code to be able to track visits:

<?php

function my_increment_post_counter() {
    if ( ! is_singular() ) {
        return;
    }

    $post = get_post();
    my_increment_post_visit_count( $post->ID );
}

function my_get_post_visit_count( $post_id ) {
    return (int) get_post_meta( $post_id, 'my_visits_counter', true );
}

function my_increment_post_visit_count( $post_id ) {
    $visits_count = my_get_post_visit_count( $post_id );
    update_post_meta( $post_id, 'my_visits_counter', (string) ++$visits_count, (string) --$visits_count);
}

add_filter( 'wp', 'my_increment_post_counter' );

The counter is stored in a post_meta field. The value is only incremented when on a singule post page.

There is also a function to get the current post visits count: my_get_post_visit_count.

Push Your Visits Count To Algolia

Now that you have a way to retrieve visits count for every post, you can add it to every Algolia post record.

<?php

function my_post_shared_attributes( array $shared_attributes, WP_Post $post) {
    $shared_attributes['visits_count'] = my_get_post_visit_count( $post->ID );

    return $shared_attributes;
}

add_filter( 'algolia_post_shared_attributes', 'my_post_shared_attributes', 10, 2 );

Now, every time a record is prepared to be sent to Algolia, the visits_count attribute will be added.

Adjust Ranking Formula

Now you want to tell Algolia to take into account the visits_count attribute for the relevancy calculation.

This can be done with the algolia_posts_index_settings filter. If you are not familiar with overriding the settings, please read the Indices Settings documentation.

The default custom ranking is configured as follow:

<?php

array(
    'desc(is_sticky)',
    'desc(post_date)',
);

To understand the best way to customize the ranking, please read Algolia's way of ranking with TIE breaking algorithm.

For this example, you will insert your visits_count in the first position of the custom ranking rules. In a real scenario, you might need to consider making different ranges of visit counts like:

  • from 0 to 100 visits => 1
  • from 0 to 500 visits => 2
  • above 2000 visits => 3

The objective here is to allow the following rules to still be considered by the changing algorithm.

Let's implement the settings adjustment:

<?php

function my_posts_index_settings( array $settings ) {
    $custom_ranking = $settings['customRanking'];
    array_unshift( $custom_ranking, 'desc(visits_count)' );
    $settings['customRanking'] = $custom_ranking;

    return $settings;
}

add_filter( 'algolia_posts_index_settings', 'my_posts_index_settings' );

Secure Your Sensitive Data

Everything you push to Algolia is securely stored. However, by default, when you perform your search queries on the frontend, every attribute is returned. Even if the data is not displayed on the page, someone could go and see the json payloads and get all of the data.

Sometimes you want your ranking algorithm to take some sensitive data into account. Let's assume that in our example the visits_count is sensitive data and that we want to avoid returning it as part of the search query result.

Here you adjust your settings:

<?php

function my_posts_index_settings( array $settings ) {
    $custom_ranking = $settings['customRanking'];
    array_unshift( $custom_ranking, 'desc(visits_count)' );
    $settings['customRanking'] = $custom_ranking;

    // Protect our sensitive data.
    $protected_attributes = [];

    if ( isset( $settings['unretrievableAttributes'] ) ) {
        // Ensure we merge our values with the existing ones if available.
        $protected_attributes = $settings['unretrievableAttributes'];
    }

    $protected_attributes[] = 'visits_count';
    $settings['unretrievableAttributes'] = $protected_attributes;

    return $settings;
}

After making changes to settings, you need to re-index the indices. To do so, click on the re-index buttons on the admin pages of this plugin, for the appropriate index being used.


Your data is now safely stored in Algolia and used in the ranking formula, but un-retrievable from the frontend!

Sync data with Algolia

To push your page visits along with your records to Algolia, click the re-index button from the admin interface.

Complete Plugin Code

Here is the complete plugin source code:

<?php
/*
Plugin Name: Visits Matter
*/

function my_increment_post_counter() {
    if ( ! is_singular() ) {
        return;
    }

    $post = get_post();
    my_increment_post_visit_count( $post->ID );
}

function my_get_post_visit_count( $post_id ) {
    return (int) get_post_meta( $post_id, 'my_visits_counter', true );
}

function my_increment_post_visit_count( $post_id ) {
    $visits_count = my_get_post_visit_count( $post_id );
    update_post_meta( $post_id, 'my_visits_counter', (string) ++$visits_count, (string) --$visits_count);
}

add_filter( 'wp', 'my_increment_post_counter' );


function my_post_shared_attributes( array $shared_attributes, WP_Post $post) {
    $shared_attributes['visits_count'] = my_get_post_visit_count( $post->ID );

    return $shared_attributes;
}

add_filter( 'algolia_post_shared_attributes', 'my_post_shared_attributes', 10, 2 );

function my_posts_index_settings( array $settings ) {
    $custom_ranking = $settings['customRanking'];
    array_unshift( $custom_ranking, 'desc(visits_count)' );
    $settings['customRanking'] = $custom_ranking;

    // Protect our sensitive data.
    $protected_attributes = array();

    if ( isset( $settings['unretrievableAttributes'] ) ) {
        // Ensure we merge our values with the existing ones if available.
        $protected_attributes = $settings['unretrievableAttributes'];
    }

    $protected_attributes[] = 'visits_count';
    $settings['unretrievableAttributes'] = $protected_attributes;

    return $settings;
}

add_filter( 'algolia_posts_index_settings', 'my_posts_index_settings' );