FCHubFCHub.co
HooksAction Hooks

Admin & Template Hooks

System-level hooks for initialisation, module activation, and injecting HTML into the checkout.

The infrastructure hooks. These fire when FluentCart boots up, when modules get activated, and when the checkout form is being rendered. Less exciting than order hooks, arguably more important — if you're building an add-on that needs to initialise alongside FluentCart or inject UI into the checkout flow, this is where it starts.


fluentcart_loaded

fluentcart_loaded — FluentCart is fully initialised and ready

Fires when: The FluentCart plugin has completed its entire bootstrap process — services are registered, database connections are established, modules are loaded, and the system is ready for business. This is the earliest safe point to interact with FluentCart's internals.

Note the naming: this hook does not use the fluent_cart/ prefix. It's just fluentcart_loaded. One of those charming inconsistencies that keeps you on your toes.

Parameters:

ParameterTypeDescription
$dataarrayEmpty array

Example:

add_action('fluentcart_loaded', function ($data) {
    // Safe to use FluentCart classes and services from here
    if (!class_exists('\FluentCart\App\App')) {
        return;
    }

    // Register custom REST API routes
    add_action('rest_api_init', function () {
        register_rest_route('my-plugin/v1', '/fluentcart-data', [
            'methods'             => 'GET',
            'callback'            => 'get_custom_fluentcart_data',
            'permission_callback' => function () {
                return current_user_can('manage_options');
            },
        ]);
    });

    // Load your plugin's FluentCart-dependent features
    require_once __DIR__ . '/includes/fluentcart-extensions.php';
}, 10, 1);

If you're building a plugin that depends on FluentCart, hook into fluentcart_loaded rather than checking class_exists on every request. It's cleaner and guarantees the full FluentCart stack is available. Just make sure FluentCart is loaded before your plugin — either by declaring it as a dependency in your plugin headers or by using a late plugins_loaded priority.


module/activated/{module_key}

fluent_cart/module/activated/{module_key} — A FluentCart module has been switched on

Fires when: A FluentCart module is activated through the admin interface. The {'{module_key}'} is the module's identifier — subscriptions, licensing, shipping, etc. Use this to run setup tasks that should only happen when a specific module is enabled.

Parameters:

ParameterTypeDescription
$dataarrayModule key and module data

Example:

// Run setup when the subscriptions module is activated
add_action('fluent_cart/module/activated/subscriptions', function ($data) {
    // Create custom database tables for subscription extensions
    global $wpdb;
    $charset = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}custom_subscription_meta (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        subscription_id BIGINT UNSIGNED NOT NULL,
        meta_key VARCHAR(255) NOT NULL,
        meta_value LONGTEXT,
        PRIMARY KEY (id),
        KEY subscription_id (subscription_id),
        KEY meta_key (meta_key(191))
    ) {$charset};";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}, 10, 1);

// Run setup when the licensing module is activated
add_action('fluent_cart/module/activated/licensing', function ($data) {
    // Schedule licence expiry cron job
    if (!wp_next_scheduled('check_licence_expirations')) {
        wp_schedule_event(time(), 'daily', 'check_licence_expirations');
    }
}, 10, 1);

This only fires at the moment of activation, not on every page load. If you need to check whether a module is currently active, use FluentCart's internal module API rather than relying on this hook.


before_checkout_form

fluent_cart/before_checkout_form — Right before the checkout form renders

Fires when: The checkout page is being rendered, immediately before the checkout form HTML is output. This is a display hook — anything you echo here appears above the form fields. Use it for trust badges, promotional banners, legal notices, or anything the customer should see before they start filling in their details.

Parameters:

ParameterTypeDescription
$dataarrayEmpty array

Example:

add_action('fluent_cart/before_checkout_form', function ($data) {
    ?>
    <div class="checkout-trust-banner" style="padding: 1rem; margin-bottom: 1.5rem; background: #f0f9ff; border-left: 4px solid #0284c7; border-radius: 4px;">
        <strong>Secure Checkout</strong> Your payment details are encrypted with 256-bit SSL.
        All transactions are processed by Stripe. We never store your card details.
    </div>
    <?php
}, 10, 1);

after_checkout_form

fluent_cart/after_checkout_form — Right after the checkout form renders

Fires when: The checkout form HTML has been output, and you can inject content below it. The mirror image of before_checkout_form. Useful for supplementary information, terms and conditions links, or additional trust signals that work better below the form.

Parameters:

ParameterTypeDescription
$dataarrayEmpty array

Example:

add_action('fluent_cart/after_checkout_form', function ($data) {
    ?>
    <div class="checkout-footer-info" style="margin-top: 1.5rem; font-size: 0.875rem; color: #6b7280;">
        <p>
            By completing this purchase, you agree to our
            <a href="/terms" target="_blank">Terms of Service</a> and
            <a href="/privacy" target="_blank">Privacy Policy</a>.
        </p>
        <div class="payment-logos" style="margin-top: 0.75rem; display: flex; gap: 0.5rem; align-items: center;">
            <img src="/wp-content/themes/your-theme/images/visa.svg" alt="Visa" height="24" />
            <img src="/wp-content/themes/your-theme/images/mastercard.svg" alt="Mastercard" height="24" />
            <img src="/wp-content/themes/your-theme/images/amex.svg" alt="Amex" height="24" />
        </div>
    </div>
    <?php
}, 10, 1);

Between before_checkout_form and after_checkout_form, you can wrap the entire checkout experience in custom context without touching FluentCart's core templates. That said, don't go overboard — the checkout page exists to collect payment, not to display your life story. Keep additions minimal and relevant.

On this page