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:
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:
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:
👨💻 Personal Brand
Wang Shiqiang | PHP / Go Technical Consultant
The English page outputs:
👨💻 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:
Personal Brand: 1
Personal Brand: 0
The English site only contains English content:
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:
[Adsterra] Native Banner - Bottom ad for all archive pages - Chinese
English:
[Adsterra] Native Banner - Bottom ad for all archive pages - English
Then, in the Twenty Twenty-Five “All Archives” template:
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:
17457
After checking the database, the two new Shortcodes can be clearly seen:
21010: Chinese
21013: English
The template obtained by get_block_template() is also the latest version:
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:
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:
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:
wp:tepll/pll-language-visibility {"lang":"zh"}
And:
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:
SWQ_ARCHIVE_TEMPLATE_TEST
SWQ_ARCHIVE_ZH_TEST
SWQ_ARCHIVE_EN_TEST
I then deleted and saved them.
A database check confirmed:
RAW DATABASE:
SWQ_ARCHIVE_TEMPLATE_TEST: NO
SWQ_ARCHIVE_ZH_TEST: NO
SWQ_ARCHIVE_EN_TEST: NO
WordPress’s get_block_template() also showed:
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:
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:
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:
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:
Performance optimized by W3 Total Cache
Served from: www.shuijingwanwq.com ... by W3 Total Cache
Further locating:
wp-content/cache/page_enhanced/www.shuijingwanwq.com/tag/git/
Corresponding cache directory.
This directory was only about 900 KB, mainly consisting of:
_index_slash_ssl.html
_index_slash_ssl.html_gzip
Comparing the HTML obtained from curl directly with _index_slash_ssl.html:
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.1can 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:
objectcache.enabled: true
objectcache.engine: redis
objectcache.enabled_for_wp_admin: false
The Database Cache is:
dbcache.enabled: false
Therefore, the Database Cache can be ruled out.
Next, I executed:
wp --allow-root \
--url="https://www.shuijingwanwq.com" \
w3-total-cache flush object
W3TC returned:
Success: Object cache successfully cleared.
Checking the Block Template again via a real HTTP request:
The previous old version:
SWQ_ARCHIVE_TEMPLATE_TEST: YES
SWQ_ARCHIVE_ZH_TEST: YES
SWQ_ARCHIVE_EN_TEST: YES
Changed to:
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:
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:
https://en.shuijingwanwq.com/tag/git/
Still returned:
ZH ad: 0
EN ad: 0
The page itself had no issues:
HTTP/2 200
<title>Git Tag Archives - Yongye</title>
canonical: https://en.shuijingwanwq.com/tag/git/
Language Visibility also correctly identified it as English:
Personal Brand: 1
Personal Brand: 0
Continuing to inspect the Block Template obtained by the real English HTTP request:
id: twentytwentyfive//archive
wp_id: 17457
length: 6832
21010: NO
21013: NO
At this point, a very familiar number appeared:
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:
wp --allow-root \
--url="https://en.shuijingwanwq.com" \
w3-total-cache flush object
Checking the English HTTP template again:
length: 7096
21010: YES
21013: YES
The change was very obvious.
Before clearing the Object Cache:
length: 6832
21010: NO
21013: NO
After clearing:
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:
wp --allow-root \
--url="https://en.shuijingwanwq.com" \
w3-total-cache flush post \
--permalink="https://en.shuijingwanwq.com/tag/git/"
Final result:
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:
Language Visibility:zh
└── [wpcode id="21010"]
English archive:
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:
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:
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:
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:
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:
wp_template
wp_template_part
And other WordPress data that genuinely requires cross-Host sync invalidation.
The goal is not to add another:
flush object
every time a new type of caching issue is discovered, but rather to let:
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:
Clear www Object Cache
→ www recovers
→ en remains unchanged
Then executing:
Clear en Object Cache
→ en recovers
Fourth, when:
Database = New
WP-CLI = New
HTTP = Old
do not repeatedly modify the page itself.
You should pivot to inspecting as early as possible:
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:
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


发表回复