1

I wrote a plugin to hit an API and display results on a page. When I was testing, every time I hit "preview", the plugin would hit the API and retrieve the most recent data. Now that the plugin is live, when I navigate to the live page, no calls are being made to the API.

Through research I believe this is a caching issue, since we want real time data, we would like that every time a user navigates to the page, the plugin fires off to the API and the most recent values are returned.

Here is a snippet of my code:

function get_count(){

//get response from api
$request = wp_remote_get('https://myapi.com/count');

if(is_wp_error($request)){
    return false;
}

//get the body from the response
$body= json_decode(wp_remote_retrieve_body($request));

//parse the body and get the count attribute
$statistic=($body->payload->count);

return '<div id="value" class="number">'. $statistic . '</div>';
}

add_shortcode('real_time_count','get_count');

How can I make this execute every time a user navigates to a page that has this shortcode?

3
  • 1
    If you use curl instead of remote_get, do you have the same experience? Mar 1, 2019 at 15:09
  • @MikeNGarrett The question says that the request to the API isn't being made, not that there was anything wrong with the result of the request. This would happen if they had some sort of caching, which the question also mentions. Mar 1, 2019 at 15:45
  • Oh. Different question entirely. Sorry about that. Mar 1, 2019 at 16:14

2 Answers 2

2

If you want to make sure the data bypasses any front-end caching, you should use AJAX to request the data and print it on the page.

What I'd suggest is keeping your shortcode, but using AJAX to update it but creating a REST API endpoint. To do this you would abstract away the API request into its own function, and then have the shortcode and API response both use that function:

/**
 * Function for retrieving the count from the API.
 */
function wpse_330377_get_count() {
    $request = wp_remote_get( 'https://myapi.com/count' );

    if( is_wp_error( $request ) ) {
        return false;
    }

    $body = json_decode( wp_remote_retrieve_body( $request ) );

    $statistic = $body->payload->count;

    return $statistic;
}

/**
 * Shortcode for outputting the count.
 */
function wpse_330377_count_shortcode() {
    $statistic = wpse_330377_get_count();

    return '<div id="value" class="number">'. $statistic . '</div>';
}
add_shortcode( 'real_time_count', 'wpse_330377_count_shortcode' );

/**
 * REST API endpoint for getting the count.
 */
function wpse_330377_register_rest_route() {
    register_rest_route( 
        'wpse_330377', 
        'count',
        [
            'method'   => 'GET',
            'callback' => 'wpse_330377_get_count'
        ]
    );
}
add_action( 'rest_api_init', 'wpse_330377_register_rest_route' );

Now you can use JavaScript to send a request to the new API endpoint, /wp-json/wpse_330377/count, which will give us the new value that we can use to update the #value div.

Create a JavaScript file like this, in your theme or plugin:

jQuery.get(
    {
        url: wpse330377.apiUrl,
        success: function( data ) {
            jQuery( '#value' ).html( data );
        }
    }
);

And then enqueue it and pass it the correct URL:

function wpse_330377_enqueue_script() {
    wp_enqueue_script( 'wpse_330377_count', 'URL TO SCRIPT GOES HERE', [ 'jquery' ], null, true );
    wp_localize_script(
        'wpse_330377_count',
        'wpse330377',
        [
            'apiUrl' => rest_url( 'wpse_330377/count' ),
        ]
    );
}
add_action( 'wp_enqueue_scripts', 'wpse_330377_enqueue_script' );

Just replace URL TO SCRIPT GOES HERE with the actual URL. Use get_theme_file_uri() to get the URL for a file in your theme, or plugins_url() if it's in a plugin.

PS: Note that I've used wpse_330377 as a prefix and namespace in many places. You should use a prefix like this to prevent conflicts with WordPress and other themes or plugins. Ideally it would be something specific to your project.

2

I missed the last part of your question :facepalm:

In this case, it depends on what your caching mechanism is on your site. Some plugins, like W3 Total Cache, allow you to mark sections of a page as non-cacheable. If this isn't an option, then Jacob's answer about using AJAX is probably the way to go. This way, you can request the data "fresh" every time.

Not what you're looking for below

You should check a couple of things. The only caching that might affect wp_remote_get would be on the response side of things, since WordPress does not cache anything it gets back in the WP_Http class's request method.

As Mike commented, do you get the same "empty" response using curl? Try this on the command line if you have curl available:

curl https://myapi.com/count

Does the response look the same as doing

curl https://myapi.com/count?foo=134134234234

?

If the responses differ, then your myapi.com server may be caching the response. If not, you need to figure out why the remote server is not sending back the expected response.

Debugging Further

If it's not caching, you should do something like this:

// In your wp-config.php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', WP_DEBUG );

In your function above:

if ( is_wp_error( $request ) ) {
    error_log( $request->get_error_message() );
}

Now, run your script, and then check the contents of /wp-content/debug.log to see if there are any errors related to your request.

If your certificate for myapi.com isn't "valid" (i.e. signed by a CA), you should look at the arg sslverify for wp_remote_get:

@type bool $sslverify Whether to verify SSL for the request. Default true.

Which can be modified like so:

wp_remote_get( 'https://myapi.com/count`, [ 'sslverify' => false ] );

If it is caching

You can use the current time to bust the cache of each request, like so:

$request = wp_remote_get( 'https://myapi.com/count?time=' . time() );
3
  • 1
    Please read the question again. The user is saying that the API request isn't even being made, because their pages are cached. When the page is cached, the shortcode function doesn't run for most visitors. The question had nothing to do with the external API being cached. Mar 1, 2019 at 15:43
  • Ack sorry, I missed the last bit about the shortcode!
    – phatskat
    Mar 1, 2019 at 15:45
  • 2
    the part about bursting the cache in the request helped me, thank you May 24, 2019 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.