Every hook and filter in FluentSnippets

Register your own snippet types, skip the runner entirely, or react when a snippet is created, updated or deleted.

FluentSnippets has a small developer surface on purpose. This is a tour of all of it, in the order you are likely to need it: turning snippets off from code, reacting to changes, and adjusting what the plugin writes to disk.

The complete reference lives in Constants and hooks. This post is about what each one is actually good for.

Turning snippets off from code

add_filter( 'fluent_snippets/run_snippets', '__return_false' );

Same effect as Safe Mode: nothing is loaded, nothing runs. The useful form is conditional:

add_filter( 'fluent_snippets/run_snippets', function ( $run ) {
    return ! ( defined( 'WP_CLI' ) && WP_CLI );
} );

Snippets stay off during WP-CLI runs — imports, migrations, cron — and on for normal requests. Swap the condition for wp_get_environment_type() === 'local' and you have a development switch.

CARE

This filter must be registered before plugins_loaded priority 9, which means it belongs in a must-use plugin or wp-config.php. Putting it in a snippet cannot work: the snippet is loaded by the very thing it is trying to disable.

Reacting to snippet changes

Four actions fire around a snippet’s lifecycle, each receiving the filename:

ActionFires
fluent_snippets/snippet_createdAfter a new snippet file is written
fluent_snippets/snippet_updatedAfter a snippet is saved
fluent_snippets/snippet_deletedAfter a snippet file is deleted
fluent_snippets/snippet_status_updatedWhen a snippet is published or unpublished

Which is enough to build an audit log — and on a site where more than one person can write code, an audit log is worth having:

foreach ( [ 'created', 'updated', 'deleted', 'status_updated' ] as $event ) {
    add_action( "fluent_snippets/snippet_{$event}", function ( $file_name ) use ( $event ) {
        error_log( sprintf(
            '[fluent-snippets] %s %s by user %d',
            $event,
            is_string( $file_name ) ? $file_name : '(unknown)',
            get_current_user_id()
        ) );
    } );
}

Put that in a must-use plugin, not a snippet, so a snippet cannot switch off its own auditing. Point it at Slack instead of error_log() and you have change notifications for the whole team.

Forcing an index rebuild

fluent_snippets/rebuild_index is both an action you can listen to and one you can fire:

do_action( 'fluent_snippets/rebuild_index' );

The index normally rebuilds itself whenever it could be stale — you save a snippet, the files on disk change, the plugin updates, the site URL changes. The one case worth firing it manually is a deploy script that has just rsynced new snippet files into place and would rather not wait for someone to load an admin page.

Guarding what gets saved

fluent_snippets/sanitize_mixed_content runs over a Content snippet’s code before it is written to disk, on both save and import. Return a WP_Error to refuse the save:

add_filter( 'fluent_snippets/sanitize_mixed_content', function ( $code, $meta ) {
    if ( str_contains( $code, 'eval(' ) ) {
        return new WP_Error( 'blocked', 'eval() is not allowed in Content snippets on this site.' );
    }
    return $code;
}, 10, 2 );

This is the hook for a house style rule — no inline eval, no third-party script hosts, a required comment header — enforced at save time rather than at review time.

Adjusting the snippet type picker

add_filter( 'fluent_snippets/snippet_types', function ( $types ) {
    $types['php_content']['running_locations']['wp_footer_late'] = [
        'label'       => 'Footer (late)',
        'description' => 'Prints at the very end of the footer.',
    ];
    return $types;
} );

One caveat that saves an afternoon: adding a location to the picker does not teach the runner how to handle it. The runner only recognises the built-in values. Treat this filter as a way to relabel and reorder what already exists, not as an extension point for new behaviour.

Storage location

define( 'FLUENT_SNIPPETS_STORAGE_DIR', WP_CONTENT_DIR . '/uploads/fluent-snippets' );

For hosts where wp-content/ is not writable, or when you want snippets inside a directory your backups already cover. Move the existing files, load an admin page once, and the index rebuilds itself.

It must stay under wp-content or uploads: the plugin derives the public URL for cached .css and .js files from this path, so a directory outside the web root breaks the load-as-file option.

Protection you can turn off

add_filter( 'fluent_snippets/protect_storage_dir', '__return_false' );

Stops the plugin writing an .htaccess into the storage directory. Only useful on nginx, or on a host that rejects the directives. If you disable it, block direct access in your server config instead — the ABSPATH guard at the top of every snippet file covers the normal case, but it is meant as defence in depth, not as the only defence.

Constants worth checking for

ConstantMeaning
FLUENT_SNIPPETS_PLUGIN_VERSIONVersion string
FLUENT_SNIPPETS_RUNNING_MUDefined when the standalone mu-plugin is running snippets
FLUENT_SNIPPETS_RUNNING_MU_VERSIONThe plugin version that runner was written from

FLUENT_SNIPPETS_RUNNING_MU is the interesting one. Code that needs to behave differently when the plugin has been removed and standalone mode has taken over can check for it.

The one hook for timing

add_action( 'fluent_snippets/after_run_snippets', function () {
    // every snippet's callbacks are now registered
} );

Fires once registration is done, during plugins_loaded. The earliest point at which you can be sure every snippet’s callbacks exist — useful when you need to reorder or remove one of them from outside.

That is the whole surface. If you need something that is not here, the storage format is documented too: snippets are PHP files with a header comment block, and File format and headers describes it well enough to generate them yourself.

Enjoyed this? Get the next one by email.

New articles, practical snippets and feature walkthroughs — sent when there's something worth reading, not on a schedule.

No spam, no selling. Unsubscribe anytime.

Custom code, without the database.

FluentSnippets is free on WordPress.org. Zero queries, no lock-in.