Journal

How to Add a Script to Your WordPress Footer (3 Safe Ways)

Three safe ways to add a script to your WordPress footer — wp_enqueue_script, wp_add_inline_script, and the wp_footer hook — plus how caching plugins like WP Rocket treat injected widgets and how to stop them breaking yours.

BBaidyanathMay 19, 20267 min readUpdated July 6, 2026
How to Add a Script to Your WordPress Footer (3 Safe Ways)

There's a rite of passage for anyone who runs a WordPress store: you paste a widget snippet into the footer, it works, you install a caching plugin for that sweet PageSpeed score, and the widget quietly vanishes. Then you spend an evening learning more about JavaScript optimisation than you ever wanted to. This post is the shortcut — the three safe ways to add a script to your footer, and how the popular caching plugins treat what you added.

First: don't echo a raw script tag

The tempting move is to drop a <script> tag straight into header.php or a wp_head callback. It works right up until something else touches the page — a caching plugin, an optimisation plugin, or a theme update. WordPress has a dependency system for scripts, and bypassing it is what creates the conflicts. Use one of the three paths below instead.

Use this for an external file. Enqueue it from your theme's functions.php (or better, a small site-specific plugin), and pass true as the in_footer argument to force footer placement so it stays off the critical rendering path and never blocks first paint.

Way 2: wp_add_inline_script attached to a handle

Use this for an inline snippet — a config object, an init call. Attach it to an enqueued handle with wp_add_inline_script, never floated on its own. Attach the config as a "before" dependency on the same handle so it arrives before the widget file loads. Keeping them on the same handle is what keeps them together when a caching plugin starts reordering things — they move as a unit.

Use this for a self-contained snippet when you'd rather not touch enqueuing. Hook a callback onto wp_footer with a late priority (20 or higher) so your snippet lands after the main content. This is the low-ceremony option — and the one most widget install guides mean when they say "paste before </body>".

async vs defer

For a self-contained third-party widget that doesn't depend on other scripts, async is the right attribute — it downloads in parallel and runs as soon as it's ready. defer is for scripts that must run in document order after the HTML is parsed (anything with dependencies). If you're not sure, a standalone widget wants async.

How caching plugins treat injected widgets

Here's where the widget "disappears". Caching plugins don't just cache HTML — they optimise JavaScript, and three optimisations in particular trip up widgets.

File combining / concatenation. Older optimisation modes merge JS files into one bundle. A third-party widget served from another domain can't be combined, and forcing it usually breaks it. Modern setups (HTTP/2 and up) mostly drop combining anyway, but if it's on, exclude the widget.

Deferring all JavaScript. Blanket defer changes execution order. A widget that expected its inline config to run first can find the config arriving late. Keeping the config attached to the same handle (the wp_add_inline_script pattern above) is most of the protection here.

Delay JS until interaction. This is the big one. "Delay JavaScript execution" holds non-critical scripts until the first scroll, tap, or mouse move — excellent for scores, because nothing non-essential runs during the initial paint. But a proactive widget — one meant to greet the visitor or offer help unprompted — looks broken if it's waiting for an interaction that might never happen. The visitor who would have engaged never sees it.

The fix in all three cases is the same: exclude the widget's script from optimisation, not disable caching. The page stays cached and fast; one script is left alone.

WP Rocket

WP Rocket is the common case, so concretely: add the widget's URL (or a recognisable substring of it) to File Optimization → Exclude JavaScript Files, and — importantly — to the "Delay JavaScript execution" exclusion list if the widget is proactive. WP Rocket already excludes the WooCommerce cart and checkout pages from caching by default, so transactional pages are safe; it's the always-on widgets on cached pages that need the exclusion.

For genuinely passive widgets — something the user has to click to open — you can leave the delay in place and get the PageSpeed benefit for free. The rule of thumb: does the widget need to do something before the user touches the page? If yes, exclude it from delay. If no, let it ride.

W3 Total Cache and LiteSpeed

The concepts map across plugins even when the menus don't. W3 Total Cache exposes minify and "Eliminate render-blocking JS" options with their own exclusion fields; LiteSpeed Cache has a "JS Excludes" / "JS Deferred Excludes" pair under Page Optimization. Same move: find the optimisation that's eating your widget, add the script to that optimisation's exclusion list.

Where to exclude a widget script, by caching plugin
PluginOptimisation that breaks proactive widgetsWhere to exclude it
WP RocketDelay JavaScript executionFile Optimization -> Delay JS exclusion list
W3 Total CacheRender-blocking JS / minifyMinify -> JS exclusions
LiteSpeed CacheJS defer / delayPage Optimization -> JS Excludes / JS Deferred Excludes
AutoptimizeAggregate + defer JSJS, CSS & HTML -> Exclude scripts from Autoptimize

A quick verification pass

After any caching change, don't trust the dashboard — trust the page. Open the live site in a private window (so you're served the cached version, not your logged-in bypass), confirm the widget appears and behaves, and check the browser console for ordering errors. For a proactive widget, specifically confirm it fires without you interacting first. Two minutes here saves the "it works on my screen" support ticket later.

How Yokaify loads on WordPress

Yokaify ships as a single async script tag pointed at the hosted widget file. The Yokaify WordPress plugin adds that line once via the wp_footer hook so you don't hand-edit theme files, and it registers the script's URL on WP Rocket's delay-exclusion list automatically — because Yokaify is a proactive widget, and a proactive widget that waits for a click it never gets is just an expensive comment in your page source. Because it's one external file, the caching plugin caches the page around it and never has to touch the widget itself.

Further reading

Last updated July 6, 2026.