
Action Hook since 1.5.1
wp_footer
Fires before </body> closing tag
Description
wp_footer is the last print slot on the front-end. Deferred scripts, analytics, and widgets that must load after content belong here.
When it runs
Front-end, inside wp_footer() at the end of the template. After the main content has rendered.
Signature
do_action( 'wp_footer' );Examples
Basic
add_action( 'wp_footer', function() {
echo '<script>console.log("Footer loaded");</script>';
} );Print a script immediately before </body>.
Real case
add_action( 'wp_footer', function() {
if ( is_user_logged_in() ) {
return;
}
echo '<script async src="https://example.com/analytics.js"></script>';
} );Load an analytics script only for logged-out visitors.
Common Use Cases
- Inject deferred JavaScript
- Add analytics snippets
- Load chat widgets
- Output footer-specific markup
Common mistakes
- Putting render-blocking CSS in wp_footer instead of enqueueing it
Related hooks
FAQ
Why is my analytics snippet blocking page render?
Large synchronous <script src> tags echoed in wp_footer still delay paint — add the async/defer attribute instead of a raw echoed tag.
Do I need to call wp_footer() myself in a block theme?
No — a block (FSE) theme has no footer.php to edit. WordPress calls wp_footer() automatically after the block template renders, so anything hooked here still prints right before </body>.
Source: wp-includes/general-template.php