I spent an hour debugging four calculators that had stopped working. No PHP error. No console error I could see at first glance. php -l said the file was fine. The markup rendered perfectly. The submit button just did nothing.
The cause turned out to be WordPress quietly rewriting my JavaScript.
The symptom
I build interactive calculators that ship as WordPress shortcodes with a small inline <script> block. They had worked for weeks. Then, after adding some content, four of them died at once.
Everything checked out:
-
php -lon every file: clean - Page returned HTTP 200
- The form, inputs and result panel were all present in the DOM
- No fatal errors in the log
The only clue was that my init guard variable was undefined in the console, meaning the IIFE never ran.
Finding it
I grabbed the inline script out of the rendered page and tried to parse it:
const src = [...document.querySelectorAll('script:not([src])')]
.find(s => s.textContent.includes('myInitFlag')).textContent;
try { new Function(src); }
catch (e) { console.log(e.message); }
// Invalid or unexpected token
A syntax error. In code I had written and linted. So I dumped the raw rendered output and searched it:
// what I wrote in PHP:
if (!isNaN(bf) && bf > 0) { ... }
// what WordPress actually sent to the browser:
if (!isNaN(bf) && bf > 0) { ... }
There it is. WordPress converted my && operator into HTML entities. One syntax error takes out the entire script block, so every handler defined below it silently never registered.
Why it happens
wptexturize is the filter that turns straight quotes into curly quotes, three dots into an ellipsis, and so on. It also normalises stray ampersands into & so the HTML validates.
That is correct behaviour for prose. It is destructive for a && inside a script tag, and wptexturize does not reliably know the difference when your content passes through certain filter chains, which is exactly what happens with shortcode output rendered inside a page builder.
The reason it is so hard to spot is that nothing errors server-side. PHP is happy. The HTML is valid. Only the browser knows, and it fails silently unless you go looking.
Fixes
1. Remove the filter where you do not need it. On pages rather than posts, so blog typography is untouched:
add_action( 'template_redirect', function () {
if ( is_page() ) {
remove_filter( 'the_content', 'wptexturize' );
remove_filter( 'widget_text_content', 'wptexturize' );
}
} );
2. Avoid && in inline scripts. Restructure the condition so the operator never appears in the output:
// instead of: if (a && b && c) { ... }
var ok = a;
if (ok) { ok = b; }
if (ok) { ok = c; }
if (ok) { ... }
Ugly, but bulletproof. I used this for the handful of expressions that survived the filter removal.
3. Move the script to a real file. The proper long-term answer. wp_enqueue_script output never passes through content filters. Inline scripts inside shortcodes are convenient and this is the price.
How to check your own site
View source on the rendered page and search inside <script> blocks for &. If it is there, this is your bug:
curl -s https://example.com/your-page/ | grep -o '&&'
A clean site returns nothing.
Takeaway
When JavaScript embedded in a CMS stops working with no error anywhere, check what the browser actually received rather than what you wrote. Content filters sit between your source and the output, and they were designed for prose, not code.
I hit this while building a set of free nutrition calculators at GramGoal — thirty-plus tools, all shortcode-rendered, which is a lot of surface area for a bug like this. It cost me an hour and four broken tools before I found it. Hopefully this saves someone else the same hour.
If you have hit other CMS filters that mangle code output, I would like to hear about them in the comments.

Top comments (0)