WordPress plugin shortcode hooks failing with specific child theme

I have a WordPress plugin that displays content using a shortcode on certain pages. The plugin works perfectly with the default Twenty Twenty-Four theme, but when I switch to a child theme called Scapeshot Wedding, the action hooks inside my shortcode stop working completely.

The issue is that my CSS and JavaScript files are not being enqueued when the child theme is active. I need these files to load properly for the plugin to function correctly. Here’s my test code to debug this:

<?php
/*
Plugin Name: Hook Test Plugin
Description: Testing action hooks with shortcodes
Version: 1.0
Author: Developer
*/

// Monitor enqueued assets
add_action('wp_head', function () {
  global $wp_scripts, $wp_styles;
  foreach ($wp_scripts->queue as $handle) {
      error_log('JS File: ' . $handle);
  }
  foreach ($wp_styles->queue as $handle) {
      error_log('CSS File: ' . $handle);
  }
});

add_action('wp_enqueue_scripts', function(){
  error_log('Global enqueue hook fired');
});

// Main shortcode function
function display_custom_content()
{
    error_log('Shortcode executed');
    
    function load_custom_styles()
    {
        error_log('Style loader called');
    }
    add_action('wp_enqueue_scripts', 'load_custom_styles', 0);

    function load_custom_scripts()
    {
        error_log('Script loader called');
    }
    add_action('wp_enqueue_scripts', 'load_custom_scripts', 0);   
}
add_shortcode('display_content', 'display_custom_content');

With the default theme, all the log messages appear. With the child theme, only the shortcode execution is logged but the enqueue hooks never fire.

What could be causing this behavior and where should I look in the theme files to fix it?

Your code has a timing issue. By the time your shortcode runs during content rendering, wp_enqueue_scripts has already fired - so adding hooks to it then is too late. That’s why you see the shortcode execution log but not the enqueue hooks. The child theme might process content differently than the default theme, making this timing problem more obvious. Hook into wp_enqueue_scripts at plugin initialization instead, then use has_shortcode() inside that hook to conditionally load assets only when the shortcode exists. Or check for the shortcode during wp or parse_query actions and set a flag to decide whether to enqueue files. Also check if the child theme’s functions.php or templates are messing with WordPress’s normal hook execution order - custom modifications there could be affecting script loading.

Yeah, it’s definitely a timing issue. wp_enqueue_scripts runs way before shortcodes get processed. Try wp_footer instead, or check if your child theme has a custom header.php that’s messing with the normal hook order.

The issue you’re facing stems from how and where the enqueue hooks are defined in your plugin’s code. Currently, you’re adding those enqueue hooks inside the shortcode function, which means they won’t execute until the shortcode itself runs during content rendering. By that time, the wp_enqueue_scripts action has already fired. To resolve this, move your enqueue functions outside of the shortcode definition. Then, you can implement a conditional check to determine if the shortcode is present on the current page, utilizing has_shortcode() or a similar function. This approach allows you to enqueue your scripts and styles globally but only when necessary. Additionally, consider that the child theme may alter the loading sequence, which can expose timing issues that didn’t appear with the default theme.