Website not updating automatically when new posts are added

Hello,

I hope someone could help me.

We just implemented Cloudflare APO in our website last Monday, unfortunately, the pages that has dynamic contents are not updating (e.g. Home and News pages). I need to manually purge these two pages so the updates will display.

Today, I made an update on our News page, instead of inserting the YouTube video directly, I have added an image when user clicked on it, the YouTube video will display. When I hit “CTRL + F5”, the changed will display BUT if I’ll just refresh the page, it won’t display and the old content displays again.

Below links are my settings for my Cloudflare:

  1. [https://snipboard.io/3RTjNe.jpg] (Cloudflare APO plugin)
  2. [https://snipboard.io/vJZlWT.jpg] (Browser Cache TTL set to Respect Existing Headers)

Below link is the display before the change made:

[https://snipboard.io/rQTOcX.jpg]

Below is the display after the change is made and hitting (CTRL + F5).

[https://snipboard.io/rQTOcX.jpg]

News page link: [Coliseum Latest News | Sports Venue | Coliseum Event]

Thank you and have a great day!

Hello,

Are you still facing this issue? I don’t see anything unusual, but…

You have posted twice the same screenshot, so we cannot see what the current page should look like.

This is what I’m seeing for the “Video of the Week” widget. Is this the current image, or an old version?
image

Hi @cbrandt,

Thanks for taking the time in responding on my concern and Yes, I’m still experiencing the issue.

The page now is displaying the updated content BUT I need to manually purged it every time I have new “News” posted. I’m not sure exactly what configuration I’m missing, I don’t have any cache plugins on my website. I only used Cloudflare’s Free account and subscribed to their APO.

Configurations:

Browser Cache TTL = Respect Existing Headers
APO = enabled (Cache TTL by Type is disabled because it’s not working too, when purging caches, the mobile display stays the same and not updating)
Page rules = did not setup anything

Also, you can check the below links so you can compare. They should have the same latest “News” but unfortunately, it’s not. The second link is displaying the older contents.

[Coliseum Latest News | Sports Venue | Coliseum Event]
[All Coliseum Summit News | Stadium and Arena Coliseum Event]

Thanks again @cbrandt and hope you can help me.

Your pages return the following header:

Vary: Accept-Encoding,User-Agent

Check your theme and plugins settings to see which of them is responsible for this, and disable it. Your vary header should only include accept-encoding. (This is probably a caching plugin setting.)

Hi @cbrandt,

I don’t have any caching plugin installed on my website. I’m dependently using the Cloudflare cache. Also, the theme I’m using is a customized one.

Hi @cbrandt,

I have this browsing caching on my .htaccess file, do you think this is the culprit?

Browser Caching

Header unset Etag
FileETag none

ExpiresActive On

Images

ExpiresByType image/jpg “access plus 1 year”
ExpiresByType image/jpeg “access plus 1 year”
ExpiresByType image/gif “access plus 1 year”
ExpiresByType image/png “access plus 1 year”
ExpiresByType image/webp “access plus 1 year”
ExpiresByType image/svg+xml “access plus 1 year”
ExpiresByType image/x-icon “access plus 1 year”

Video

ExpiresByType video/mp4 “access plus 1 year”
ExpiresByType video/mpeg “access plus 1 year”

CSS, JavaScript

ExpiresByType text/css “access plus 1 month”
ExpiresByType text/javascript “access plus 1 month”
ExpiresByType application/javascript “access plus 1 month”

Others

ExpiresByType application/pdf “access plus 1 month”
ExpiresByType application/x-shockwave-flash “access plus 1 month”

Does your theme set the vary header? If not you’ll need to find out what is setting it.

No, it is not.

No, it’s not. I’m using bootstrap template for it. By the way, Is it okay if I’ll set my browser cache to 1 month?

One more question, this “vary” setting is the culprit too why "caching by ttl type’ is not working too? Thank you so much for your help.

I can also see this on my homepage BUT when I have new “News”, the page is updating.

[https://www.coliseum-online.com/]

This needs to be considered within the context of how your theme handles changes in filenames. If a CSS file, for instance, is changed, the theme (or the relevant plugin) should change either it’s name, or its version via query string. Otherwise a visitor who’s visited the site may get the old “appearance” for a while.

But this is irrelevant to what we’re discussing here, which is the caching of HTML, which is what APO does.

Yes, I understand. But this issue is not easy to troubleshoot and we need to remove any possible signal that may be at play. Did you set the vary header intentionally?

Hi @cbrandt,

Not sure on this BUT I will try to check my theme files, if something there is setting this header. Does this header doesn’t come in Cloudflare?

Hi @cbrandt,

I will try to check my theme files and plugins for this. To confirm, the value should only be “Vary: Accept-Encoding”? Thanks again.

No. This is a header coming out of your origin. You can use the String Locator plugin to find it on your WordPress installation. If you did not create your theme yourself, you should be careful before editing any theme files. Make sure you always use a child theme, and check with your theme developer before making any changes.

Hi @cbrandt,

I will get back and will let you know if I’ll find it. Thank you so much for your help.

1 Like

Hi,

I’ve been testing the issue you’re facing, and the issue seems to be related to both how APO handles cache invalidation, and how WordPress tells visitors that content has changed.

When you update a post, this post is updated on WordPress database and the “Last-Modified” header is updated accordingly. That is a signal for browsers to request the new version, instead of using the one it has on cache.

WordPress is known for messing up with the Last-Modified header, which is understandable, since when we talk WordPress we are actually talking all kinds of configurations (server, wp-config.php, .htaccess, theme, plugins etc.)

One issue is that when post 1 is updated, post 2 is not, even when it has a “Latest Posts” widget or similar feature to show the most recent posts on a page. So WordPress does not change the Last-Modified header for post 2 when post 1 is updated, rendering post 2 from the cached, outdated version of the content.

This blog post explains the issue in detail and has a good solution that you’d need to adjust to your needs. It makes WordPress update the homepage if other posts are updated, but not all pages with the Latest Posts widget on them.

On the APO end, it seem that APO in trying to maximize efficiency and reduce visits to the origin server does not revalidate correctly. I don’t know why, so I can’t explain. But I’ve spent some time testing different configurations and here one that worked on a test website under APO with both a page and a post with the Latest Posts widget.

  1. Implement proper “Last-Modified”, if needed.

  2. Create a Cache Rule for the pages with cacheable dynamic content (those with the Latest Posts widget or similar features.):When incoming requests match:
    Hostname equals apo.example.com (whatever hostname you're running APO on.)
    URI Path is in "/path-1/ /path-2/ /path-3/"
    then
    Eligible for Cache
    Edge Cache TTL: 10 seconds

  3. Alternatively, you may implement the Cache Rule above withEdge Cache TTL: Respect origin.But then you must send a header from the origin defining the Edge Cache TTL:Cloudflare-CDN-Cache-Control: max-age=10
    Obs.: A Cache-Control header with “s-maxage” will not work.

  4. After testing, and confirming it’s working as expected, you may want to adjust the time set with the either method for Edge Cache TTL according to how often your content changes, and how soon users must see the updated content. It should go without saying that the smaller the time, the less efficient the caching will be. I started with 10 seconds to make testing easier.

Remember to purge the Cloudflare Cache for the relevant pages after implementing the changes. To test, make minor content changes that would affect the Latest Posts widget, such as changing the title or excerpt, or removing/adding a post. As with anything WordPress, I can’t guarantee it will work for every one. It worked for me,

Hi @cbrandt,

Thanks for helping me on this issue. I’d like to try your suggestions you have provided. Also, I wanted to implement this code (see below) from here BUT instead of just homepage, I wanted to implement it in all “Pages” and “Posts”. How should I do that using the code below?

/**
 * Set the Last-Modified header for visitors on the front-page 
 * based on when a post was last modified.
 */

add_action( 'template_redirect', function() use ( &$wp )
{
    // Only visitors (not logged in)
    if( is_user_logged_in() )
        return;

    // Target front-page
    if( ! is_front_page() )
        return;

    // Don't add it if there's e.g. 404 error (similar as the error check for feeds)
    if( ! empty( $wp->query_vars['error'] ) )
        return;

    // Don't override the last-modified header if it's already set
    $headers = headers_list();
    if( ! empty( $headers['last-modified'] ) )  
        return;

    // Get last modified post
    $last_modified = mysql2date( 'D, d M Y H:i:s', get_lastpostmodified( 'GMT' ), false );

    // Add last modified header
    if( $last_modified && ! headers_sent() )
        header( "Last-Modified: " . $last_modified . ' GMT' );

}, 1 );

Hi @cbrandt,

I have used the code below and it seems it’s working BUT not on my “News” page which I have used a custom page template. I need to update the “News” page manually (changing the date of published will do the trick) so the cache will be purge. It’s not working automatically.

add_action(‘template_redirect’, ‘theme_add_edge_cache_ttl’);

function theme_add_edge_cache_ttl($headers) {
if (!is_user_logged_in()) {
global $post;
if (isset($post) && isset($post->post_modified)) {
$post_mod_date = date(“D, d M Y H:i:s”, strtotime($post->post_modified));
header(‘Cache-Control: public, max-age=’ . (strtotime(‘+1 week’, strtotime($post->post_modified)) - time()));
header(‘Expires: ’ . gmdate(‘D, d M Y H:i:s’, strtotime(’+1 week’, strtotime($post->post_modified))) . ’ GMT’);
}
}
}

add_action(‘save_post’, ‘theme_clear_edge_cache_on_update’, 10, 3);

function theme_clear_edge_cache_on_update($post_id, $post, $update) {
// Clear the Cloudflare Edge Cache for the updated post or page
if (function_exists(‘cloudflare_clear_cache’) && !$update) {
$post_url = get_permalink($post_id);
cloudflare_clear_cache(array($post_url));
}
}

Hi,

I’m glad it’s working for the home page. That code explicitly limits itself to the homepage with the is_front_page() function, and you’d need to modify that line somehow to make it work for other pages (but not the whole website.)

TBH, I’m not sure how to do it, and these are questions that fall outside the scope of this Community. You should raise them in dedicated forums, such as WordPress support forums or https://wordpress.stackexchange.com/, as the answer to one question may lead to other issues and questions related to your own specific WordPress installation.