没有不值得去解决的问题,也没有不值得去学习的技术!

WordPress Three-Domain Architecture Pitfalls: Adsterra Archive Ads Fail to Work, Traced to W3TC Object Cache

WordPress Three-Domain Architecture Pitfalls: Adsterra Archive Ads Fail to Work, Traced to W3TC Object Cache

作者:

Recently, I prepared to continue testing Adsterra.

Previously, I had already added a Native Banner at the end of article content on both the Chinese and English sites. Since Adsterra’s current traffic volume is still very small, I do not plan to scale up ads immediately. Instead, I intend to add a relatively restrained placement:

Adding another Native Banner at the bottom of the article list on archive pages such as categories and tags.

Originally, this should have been a very simple WordPress template modification.

However, during the actual process, I successively suspected WPCode, PHP Snippet, Shortcode, Twenty Twenty-Five Block Template, Language Visibility, EdgeOne, and W3 Total Cache Page Cache, before finally confirming:

The real problem still stemmed from W3 Total Cache Object Cache under the multi-domain architecture.

More precisely, the same WordPress Block Template had already been updated in the database, but front-end requests from different Hosts for www and en were still fetching the old template from the Redis Object Cache.

This also made me realize once again: the multi-domain caching issue I had already resolved once in mid-July did not truly cover all editable objects in WordPress.

1. Current WordPress Multi-Domain Architecture

Currently, the website primarily uses three domains:

Plaintext
admin.shuijingwanwq.com
www.shuijingwanwq.com
en.shuijingwanwq.com

Among them:

admin.shuijingwanwq.com is used for the WordPress admin dashboard, bypassing the front-end CDN.

www.shuijingwanwq.com is the Chinese site, currently using EdgeOne.

en.shuijingwanwq.com is the English site, currently using Cloudflare.

These three are not three separate WordPress installations.

They share the same WordPress codebase and the same database, while W3 Total Cache’s Object Cache uses Redis.

The reason for separately adding admin.shuijingwanwq.com was not simply to split domains.

Previously, when WordPress admin operations went through the front-end CDN, issues such as timeouts during long requests like core upgrades occurred. Therefore, an independent admin domain was specifically set up later.

This process has been documented previously:

Therefore, I do not plan to remove the admin domain just because of this issue.

What truly needs to be resolved next is the cache consistency issue when multiple Hosts share WordPress.

2. This Time, I Originally Just Wanted to Add a Second Adsterra Ad Slot

The Adsterra ads at the end of article pages had already been implemented via WPCode.

The Chinese and English sites use different Native Banner ad codes:

The Chinese site uses one ad unit, and the English site uses another.

The plan this time was to add:

Ads at the bottom of the article list on all archive pages.

That is, including tag pages, category pages, and other pages using the “All Archives” template.

Initially, I still planned to use a PHP Snippet to determine whether to output the Chinese or English ad based on the current Host.

The general logic was:

PHP
if ( 'www.shuijingwanwq.com' === $host ) {
	// 输出中文 Adsterra。
}

if ( 'en.shuijingwanwq.com' === $host ) {
	// 输出英文 Adsterra。
}

Looking back now, this PHP logic most likely had no issues.

However, at the time, the expected ads were still not visible on the front end.

As I continued analyzing, the contributing factors multiplied:

WPCode auto-insertion positions, Block Theme rendering order, Shortcodes, archive templates, caching, and multilingual logic were all tangled together.

Considering that the time investment was becoming increasingly uncontrollable, I decided to stop verifying the PHP approach for now.

3. Switching to the Long-Verified Language Visibility

My WordPress site was already using Language Visibility.

For example, the personal brand information on the blog homepage:

The Chinese page outputs:

Plaintext
👨‍💻 Personal Brand
Wang Shiqiang | PHP / Go Technical Consultant

The English page outputs:

Plaintext
👨‍💻 Personal Brand
Wang Shiqiang | PHP & Go Technical Consultant

After actually fetching the page HTML, it can be confirmed:

The Chinese site only contains Chinese content:

Plaintext
Personal Brand: 1
Personal Brand: 0

The English site only contains English content:

Plaintext
Personal Brand: 0
Personal Brand: 1

In other words, it does not output both languages and then hide one via CSS; rather, it decides whether to actually render the block based on the current language.

Since the existing solution was already proven stable, I decided not to manually determine the Host within a single PHP Snippet anymore, but instead split it into two independent HTML Snippets.

Chinese:

Plaintext
[Adsterra] Native Banner - Bottom ad for all archive pages - Chinese

English:

Plaintext
[Adsterra] Native Banner - Bottom ad for all archive pages - English

Then, in the Twenty Twenty-Five “All Archives” template:

Plaintext
Query Loop
Pagination

Language Visibility: Chinese
└── Chinese Adsterra Shortcode

Language Visibility: English
└── English Adsterra Shortcode

This way, each component bears only a single responsibility:

The WordPress template handles the ad placement.

Language Visibility handles the language.

The WPCode HTML Snippet handles storing the ad code.

This structure is clearly easier to understand than having a single PHP Snippet handle both domain recognition and ad output.

4. But After Modifying the Template, the Front End Still Had No Ads

This is exactly where the problem started getting weird.

The “All Archives” template ID in the database is:

Plaintext
17457

After checking the database, the two new Shortcodes can be clearly seen:

Plaintext
21010: Chinese
21013: English

The template obtained by get_block_template() is also the latest version:

Plaintext
source: custom
wp_id: 17457
21010: YES
21013: YES

There were no issues with the two WPCode Snippets themselves either.

When directly executing the Shortcode:

Plaintext
21010
shortcode_container: FOUND

21013
shortcode_container: FOUND

Therefore, the following can be ruled out:

Errors in the WPCode HTML Snippet itself.

Shortcode failing to execute.

Ad code failing to save successfully.

Next, I checked Language Visibility.

The structure of the archive template is:

Plaintext
wp:tepll/pll-language-visibility {"lang":"zh"}

wp:tepll/pll-language-visibility {“lang”:”en”}

Meanwhile, the personal brand block already running normally on the blog homepage also uses:

Plaintext
wp:tepll/pll-language-visibility {"lang":"zh"}

And:

Plaintext
wp:tepll/pll-language-visibility {"lang":"en"}

Thus, no issues were found with the Language Visibility template structure either.

5. The Real Anomaly: The Database and Real HTTP Requests Saw Two Different Templates

To further confirm the issue, I temporarily added a few test markers to the “All Archives” template.

For example:

Plaintext
SWQ_ARCHIVE_TEMPLATE_TEST
SWQ_ARCHIVE_ZH_TEST
SWQ_ARCHIVE_EN_TEST

I then deleted and saved them.

A database check confirmed:

Plaintext
RAW DATABASE:
SWQ_ARCHIVE_TEMPLATE_TEST: NO
SWQ_ARCHIVE_ZH_TEST: NO
SWQ_ARCHIVE_EN_TEST: NO

WordPress’s get_block_template() also showed:

Plaintext
RESOLVED TEMPLATE:
SWQ_ARCHIVE_TEMPLATE_TEST: NO
SWQ_ARCHIVE_ZH_TEST: NO
SWQ_ARCHIVE_EN_TEST: NO

21010: YES
21013: YES

In other words, both the database and WP-CLI were already seeing the latest version of the template.

However, front-end HTTP requests could still surprisingly see:

Plaintext
SWQ_ARCHIVE_TEMPLATE_TEST
SWQ_ARCHIVE_ZH_TEST

This meant the problem could no longer just be:

“Forgot to save the template.”

“Language Visibility settings error.”

“Shortcode did not execute.”

At this point, caching became the primary suspect.

6. First Ruling Out the CDN

The Chinese site currently uses EdgeOne.

If a normal request:

Plaintext
https://www.shuijingwanwq.com/tag/git/

returns an old page, then of course it could just be an EdgeOne cache.

Therefore, during testing, I used:

Bash
curl \
    --resolve www.shuijingwanwq.com:443:127.0.0.1 \
    https://www.shuijingwanwq.com/tag/git/

This way, the HTTPS Host remained www.shuijingwanwq.com, but the actual connection was to the local server 127.0.0.1.

This bypassed EdgeOne.

However, the old page still persisted.

So the problem was not solely in the CDN.

7. W3TC Page Cache Did Exist, But Was Not the Ultimate Root Cause

Continuing to inspect the response, I could see:

Plaintext
Performance optimized by W3 Total Cache
Served from: www.shuijingwanwq.com ... by W3 Total Cache

Further locating:

Plaintext
wp-content/cache/page_enhanced/www.shuijingwanwq.com/tag/git/

Corresponding cache directory.

This directory was only about 900 KB, mainly consisting of:

Plaintext
_index_slash_ssl.html
_index_slash_ssl.html_gzip

Comparing the HTML obtained from curl directly with _index_slash_ssl.html:

Plaintext
SHA256 exactly identical
RESULT: EXACTLY SAME

Thus, it can be confirmed:

Even when bypassing EdgeOne via 127.0.0.1, it could still directly hit the W3TC Disk Enhanced Page Cache.

This is a point very much worth remembering for future troubleshooting:

--resolve ...:127.0.0.1 can only bypass the CDN, not the Page Cache on the WordPress server itself.

However, after merely clearing the Page Cache for /tag/git/, the issue could still reappear.

So Page Cache was not the underlying root cause.

8. The Real Breakthrough: Clearing the W3TC Object Cache

The current W3 Total Cache configuration confirms:

Plaintext
objectcache.enabled: true
objectcache.engine: redis
objectcache.enabled_for_wp_admin: false

The Database Cache is:

Plaintext
dbcache.enabled: false

Therefore, the Database Cache can be ruled out.

Next, I executed:

Bash
wp --allow-root \
    --url="https://www.shuijingwanwq.com" \
    w3-total-cache flush object

W3TC returned:

Plaintext
Success: Object cache successfully cleared.

Checking the Block Template again via a real HTTP request:

The previous old version:

Plaintext
SWQ_ARCHIVE_TEMPLATE_TEST: YES
SWQ_ARCHIVE_ZH_TEST: YES
SWQ_ARCHIVE_EN_TEST: YES

Changed to:

Plaintext
SWQ_ARCHIVE_TEMPLATE_TEST: NO
SWQ_ARCHIVE_ZH_TEST: NO
SWQ_ARCHIVE_EN_TEST: NO

21010: YES
21013: YES

At this point, the problem was basically pinpointed:

The W3TC Redis Object Cache used by the www front end had retained the old version of the Block Template.

I then cleared the Page Cache for /tag/git/ again, allowing it to regenerate the page based on the new Object Cache.

The final result for the Chinese site:

Plaintext
TEST MARKERS: 0

ZH ad: 1
EN ad: 0

The Chinese archive ads were finally working normally.

9. But the English Site Still Had No Ads

I thought the problem was over at this point.

However, the English site:

Plaintext
https://en.shuijingwanwq.com/tag/git/

Still returned:

Plaintext
ZH ad: 0
EN ad: 0

The page itself had no issues:

Plaintext
HTTP/2 200
<title>Git Tag Archives - Yongye</title>
canonical: https://en.shuijingwanwq.com/tag/git/

Language Visibility also correctly identified it as English:

Plaintext
Personal Brand: 1
Personal Brand: 0

Continuing to inspect the Block Template obtained by the real English HTTP request:

Plaintext
id: twentytwentyfive//archive
wp_id: 17457
length: 6832
21010: NO
21013: NO

At this point, a very familiar number appeared:

Plaintext
6832

This was exactly the old archive template that had appeared multiple times before.

In other words:

The Chinese site was already using the new template, but the English site was still holding onto the old one.

10. Clearing the Object Cache for www Does Not Automatically Resolve en

I then switched to executing it within the English Host context:

Bash
wp --allow-root \
    --url="https://en.shuijingwanwq.com" \
    w3-total-cache flush object

Checking the English HTTP template again:

Plaintext
length: 7096
21010: YES
21013: YES

The change was very obvious.

Before clearing the Object Cache:

Plaintext
length: 6832
21010: NO
21013: NO

After clearing:

Plaintext
length: 7096
21010: YES
21013: YES

This further proves:

The Object Caches under the Chinese and English Hosts actually maintain independent cache states.

Finally, I cleared the English /tag/git/ Page Cache:

Bash
wp --allow-root \
    --url="https://en.shuijingwanwq.com" \
    w3-total-cache flush post \
    --permalink="https://en.shuijingwanwq.com/tag/git/"

Final result:

Plaintext
TEST MARKERS: 0

ZH ad: 0
EN ad: 1

At this point, both the Chinese and English archive ads were completely normal.

11. The Final Retained Ad Implementation Is Actually Very Simple

After a long troubleshooting journey, the final ad solution was surprisingly simple.

Chinese archive:

Plaintext
Language Visibility:zh
└── [wpcode id="21010"]

English archive:

Plaintext
Language Visibility:en
└── [wpcode id="21013"]

Both WPCode entries are just HTML Snippets.

No more writing custom PHP to determine the domain.

However, it must be emphasized:

This does not mean the previous PHP approach was flawed.

On the contrary, judging from the caching phenomena discovered later, the previous PHP approach would likely have worked perfectly fine as well.

The reason I switched to Language Visibility at the time was not because the PHP implementation had been proven wrong, but because continuing to troubleshoot the PHP auto-insertion approach would introduce more and more variables.

To cut my losses in time, I chose to use the Language Visibility solution that was already verified on the site.

And ultimately, I found that both the PHP approach and the Language Visibility approach might have been affected by the same underlying issue:

The old W3TC Object Cache prevented the front end from fetching the latest Block Template at all.

If the template itself was old, then whether the upper layer used PHP or Shortcode was no longer the key issue.

12. This Issue Is Very Similar to the Previous Multi-Domain Object Cache Problem

Actually, this was not the first time I encountered a similar issue.

Previously, after setting up admin.shuijingwanwq.com and completing the English subdomain migration, I had already analyzed:

Plaintext
admin
www
en

Although they use the same WordPress, the same database, and Redis, W3 Total Cache’s Object Cache is affected by the Host.

At that time, I had already designed cache synchronization handling for scenarios like regular posts and implemented the corresponding MU plugin.

As far as I recall, this plugin is:

Plaintext
swq-w3tc-polylang-purge.php

The previous focus was mainly on regular posts, Polylang multilingual relationships, and related cache invalidation.

But this time, a new gap was exposed:

Plaintext
post_type = wp_template

Which is the WordPress Block Template.

The database had been updated, but the front-end Object Cache for www and en had not synchronously invalidated.

This means the existing MU plugin likely still needs further expansion.

13. A More Severe Phenomenon Than Adsterra: The Homepage Is Still Stuck on July 28

Actually, there is currently a more pressing issue worth prioritizing.

As of July 31, 2026, I noticed that the latest articles displayed on the website homepage were still stuck on:

July 28.

In other words, this archive ad issue merely brought the problem to light again.

If even the latest articles on the homepage cannot be updated in time, then the impact is no longer limited to:

“Why aren’t the new ads showing up.”

It may also include:

The latest articles list.

Category and tag pages.

Block Templates.

Multilingual pages.

Other dynamic content relying on WordPress query results.

This is enough to show:

The cache consistency issue should be elevated to one of the highest priorities for current website maintenance.

14. Next Steps: Stop Adding Patches, Improve the Existing MU Plugin Instead

The ads are now displaying normally, so I will not continue researching the previous PHP approach for the time being.

What is more important now is to go back and inspect the existing:

Plaintext
swq-w3tc-polylang-purge.php

Re-examine exactly which events it currently handles:

What gets cleared after a regular post is saved.

How the Chinese and English Hosts synchronize.

How posts:last_changed updates.

How the Object Cache invalidates.

How the Page Cache invalidates.

Then focus on supplementing the previously uncovered objects, such as:

Plaintext
wp_template
wp_template_part

And other WordPress data that genuinely requires cross-Host sync invalidation.

The goal is not to add another:

Plaintext
flush object

every time a new type of caching issue is discovered, but rather to let:

Plaintext
admin saves content

Identify what this modification affects

Synchronously invalidate the corresponding caches for www / en

The next front-end request naturally generates the new version

Form a stable, automated closed loop.

15. Key Takeaways from This Troubleshooting Worth Remembering

First, curl --resolve host:443:127.0.0.1 can bypass the CDN, but you cannot assume it also bypasses the W3TC Page Cache.

Second, clearing the Page Cache does not necessarily solve the problem.

If the upstream Object Cache still holds old data after the Page Cache is deleted, the regenerated page may still be the old one.

Third, under the current multi-domain architecture, you cannot simply assume that clearing the Object Cache once will cover all Hosts.

The actual verification this time was:

Plaintext
Clear www Object Cache
→ www recovers
→ en remains unchanged

Then executing:

Plaintext
Clear en Object Cache
→ en recovers

Fourth, when:

Plaintext
Database = New
WP-CLI = New
HTTP = Old

do not repeatedly modify the page itself.

You should pivot to inspecting as early as possible:

Plaintext
Object Cache
Page Cache
Host

Fifth, you cannot conclude that the original implementation was definitely wrong just because you ultimately switched to a different one.

Switching from PHP to Language Visibility this time was merely to reduce variables and cut losses in time.

In hindsight, both approaches likely had no real issues.

16. Final Thoughts

This originally started as just a plan to add an Adsterra Native Banner to the archive pages.

In the end, I spent a massive amount of time troubleshooting WordPress templates, WPCode, Shortcodes, Language Visibility, EdgeOne, W3 Total Cache Page Cache, and Redis Object Cache.

Technically speaking, the problem was finally identified this time.

But in terms of time invested, this is not something to be happy about.

Because the purpose of the website infrastructure should originally be to help me more stably:

Write blog posts, translate articles, improve English content, and test ads and affiliate marketing.

If every minor template modification requires hours to confirm:

Plaintext
What is the state of admin?
What is the state of www?
What is the state of en?
Has the Object Cache been cleared?
Has the Page Cache been cleared?
Has the CDN updated?

then the caching system itself has begun to encroach on the time that should genuinely be invested in content production.

So next, I will temporarily stop adding new caching logic or new ad implementations.

The next step should be to first re-examine the existing multi-domain cache synchronization mechanism thoroughly and improve the existing MU plugin.

Especially since the latest articles on the homepage are still stuck on July 28, which is more worthy of prioritizing than the archive ads not displaying.

Once this issue is truly resolved, continuing with subsequent ad and content work should be much easier.

系列导航

需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理