The tracking tag we assigned after using it
What we hit
Our shell script, wp-blog/auto-post/auto_post_blog.sh, automatically published 33 articles a day across 8 sites. The posts went live, and the logs reported success. But the affiliate links being published had an empty tracking parameter: .../s?k=...&tag=. Clicks through those links earned nothing.
The measurement on 2026-09-12 recorded 1,040 published articles, with 152 containing empty tags and 98 containing populated tags. On the main site, the counts were 741 published, 52 with empty tags, and 0 with populated tags. The English site had 29, 21, and 0 respectively; the global blog had 20, 14, and 0. The remaining sites together accounted for 250 published, 65 with empty tags, and 98 with populated tags.
The publishing operation was succeeding. The links inside its output were failing at the purpose we needed them to serve. That distinction did not appear in the success log.
What we assumed
The script contained code that assigned TRACKING_ID. Reading that assignment made it look as though the tracking configuration was present and doing its job.
The surrounding code reinforced that impression. The same case block also assigned CATEGORY, and the script used CATEGORY afterward. The block therefore had an observable role in the publishing flow. But the assigned TRACKING_ID was never used afterward.
We had treated the presence of an assignment as evidence that its value reached the generated article. Those are different claims. A variable can be assigned correctly in a script and still contribute nothing to the operation that needs it.
The log gave us another incomplete signal. It reported ✅ Success: <URL> because the post itself had succeeded. That message said nothing about whether the article contained a usable tracking tag. We were looking at evidence of publication without checking the part of the published content that determined whether affiliate clicks could earn anything.
What was actually true
The article-generation prompt referenced ${TRACKING_ID} around line 43. The case statement that assigned TRACKING_ID was around line 88, after the prompt.
The shell evaluated the script in order. When it constructed the prompt, the variable was unset, so the reference expanded to an empty string. Assigning the variable later could not change the prompt that had already been constructed.
There was no set -u to turn the undefined reference into an error. The empty value passed through silently. After the later assignment, nothing read TRACKING_ID, so that assignment could not repair the earlier omission either.
This explained why the script could look configured and continue publishing successfully while emitting empty tags. The assignment existed, the category value from the same block was used, and the posting operation completed. None of those facts established that the tracking value was available when the prompt needed it.
The fix
We moved the case block before the prompt. That corrected the ordering error: the tracking value now existed before the shell expanded the reference.
We also added a post-generation sed replacement that forcibly overwrote the tracking tag. The source of the empty prompt value was fixed, but the generator could still drop the tag or write a different ID despite the prompt's instructions. The generated output needed its own correction.
The replacement included the query delimiter, matching ?tag= or &tag= together. That detail kept the replacement from breaking data-tag="". We needed to change the tracking parameter in links without damaging an attribute that happened to contain the same text.
Finally, we made an empty TRACKING_ID stop publication with exit 1. A missing tracking value would now prevent the post instead of allowing another apparently successful publication with a broken affiliate link.
These changes covered the assignment order, the generated tag, and the decision to publish. Each addressed a place where the value could otherwise fail to reach the article.
The database was fixed, but the pages were not
After the database repair, the empty-tag count went from 152 to 0, and the populated-tag count went from 98 to 250. Plain requests to live pages still returned empty tags.
The cause was page caching. The database contained the repaired links, but cached HTML continued reaching visitors. A request with a cache-bypass query showed the populated tag; an ordinary request still showed the empty one.
On the main site, wp-super-cache was active, but wp super-cache flush was not a registered command. We deleted wp-content/cache/supercache, removing 118 files. For sites using wp-fastest-cache, there was no WP-CLI command, so we deleted the page-cache directories, including wp-content/cache/all.
wp cache flush cleared only the object cache. It did not clear these page caches.
After deletion, we verified populated tags on 4 sites using plain requests. The verification had to inspect what visitors actually received, without a cache-bypass query.
The lesson
We learned that code assigning a value does not prove the value reaches its consumer. A successful publication log does not establish that the published links are correct, and a repaired database does not establish that readers receive the repair. We need to inspect the generated links themselves and verify live pages after clearing their caches. The check is complete when the required value appears in the output readers receive.
Root Cause is written by TechAthletes. We run the agents behind pipelines like this side by side in Agent Tile, our macOS app for keeping many Claude Code sessions in view at once.