PHP hooks
Snipfire is built to be extended: Snipfire Pro itself plugs in only through these hooks. Put your code in a plugin or mu-plugin rather than a snippet, so it's in place before snippets run.
Access and permissions
snipfire_capability (filter)
The capability that gives full Snipfire access, besides administrators. Default manage_options. Not used on multisite, where only super admins have full access.
add_filter( 'snipfire_capability', fn() => 'edit_theme_options' );
snipfire_user_access (filter)
The access level for a user who isn't an administrator: none, view, design or full. With Snipfire Pro, the level comes from team access (at priority 10); use a later priority to override it for one person.
add_filter( 'snipfire_user_access', function ( $level, $user_id, $user ) {
return 'jane' === $user->user_login ? 'design' : $level;
}, 20, 3 );
snipfire_access_changed (action, Pro)
Fires when team access changes. Arguments: the role → level map before and after.
Snippets and history
snipfire_revisions_limit (filter)
How many versions of each snippet to keep. Default 10, or 50 with Pro.
add_filter( 'snipfire_revisions_limit', fn() => 100 );
snipfire_validate (filter)
Add your own errors or warnings before a snippet is saved. An error keeps the snippet switched off.
add_filter( 'snipfire_validate', function ( $result, $snippet ) {
if ( 'php' === $snippet['type'] && str_contains( $snippet['code'], 'eval(' ) ) {
$result['errors'][] = array( 'message' => 'eval() is not allowed on this site.', 'line' => 0 );
}
return $result;
}, 10, 2 );
$result is array( 'errors' => array( array( 'message' => …, 'line' => … ) ), 'warnings' => array( 'text', … ) ).
snipfire_snippet_output (filter)
Filters an HTML snippet's or shortcode's output before it's printed. Arguments: $html, $meta (the snippet's settings, without code).
snipfire_activity (action)
Fires on every change: $action (created, updated, enabled…), $snippet (settings, or null for settings changes), $details. The activity log listens to it; you can too, for example to post changes to Slack.
add_action( 'snipfire_activity', function ( $action, $snippet, $details ) {
if ( 'auto_disabled' === $action ) {
wp_mail( get_option( 'admin_email' ), 'Snippet switched off', $snippet['title'] . ': ' . ( $details['message'] ?? '' ) );
}
}, 10, 3 );
For auto_disabled, $details holds the error's message and line.
snipfire_active_snippets (action)
Fires after the active snippets are hooked in (not in safe mode or on Snipfire's own screens). Argument: active snippets, id => settings.
Conditions
snipfire_condition_types, snipfire_condition_labels, snipfire_condition_groups (filters)
Add your own condition rules. A type has a kind (value shape: none, text, multi, list, ids, keyvalue, number, range), ops, a stage (0 = any time, 1 = user known, 2 = page known) and a match callable that returns true, false or null ("can't tell", which never matches).
Don't translate anything in snipfire_condition_types: it runs while snippets load. Put names in snipfire_condition_labels.
use Snipfire\Conditions;
add_filter( 'snipfire_condition_types', function ( $types ) {
$types['acme_member'] = array(
'kind' => 'none',
'ops' => Conditions::SET_OPS, // is, is_not
'stage' => 1, // needs the user
'match' => fn( $rule, $ctx ) => function_exists( 'acme_is_member' ) ? acme_is_member() : null,
);
return $types;
} );
add_filter( 'snipfire_condition_labels', function ( $labels ) {
$labels['acme_member'] = array( 'label' => __( 'Visitor is an Acme member', 'acme' ) );
return $labels;
} );
add_filter( 'snipfire_condition_groups', function ( $groups ) {
$groups[ __( 'Visitor', 'snipfire' ) ]['acme_member'] = __( 'Acme member', 'acme' );
return $groups;
} );
snipfire_visitor_country (filter, Pro)
The visitor's country for the Country rule: a two-letter code, or '' when unknown. Use it to plug in your own geolocation.
Importers
snipfire_import_sources (filter)
The list of importer classes. Add your own class extending Snipfire\Import\Source to import from another plugin.
AI abilities
snipfire_abilities (action)
Fires after Snipfire registers its WordPress abilities (WordPress 6.9+). Argument: the Snipfire\Abilities object. Register your own abilities here, in the snipfire category, and pass Snipfire\Abilities::meta() as their meta so they're only offered to AI assistants and the REST API when Tools & Safe Mode → AI assistants is on.
add_action( 'snipfire_abilities', function () {
wp_register_ability( 'acme/list-snippet-notes', array(
'label' => __( 'List snippet notes', 'acme' ),
'description' => __( 'Lists the notes Acme keeps about snippets.', 'acme' ),
'category' => Snipfire\Abilities::CATEGORY,
'input_schema' => array( 'type' => 'object', 'default' => array() ),
'output_schema' => array( 'type' => 'array' ),
'execute_callback' => 'acme_snippet_notes',
'permission_callback' => Snipfire\Abilities::allowed( 'view' ),
'meta' => Snipfire\Abilities::meta( true ), // read-only
) );
} );
Abilities::allowed( 'view' | 'design' | 'full' ) checks the user's Snipfire access level, as Snipfire's own abilities do.
Activity log (Pro)
snipfire_activity_months(filter): months to keep. Default 12.snipfire_log_activity(filter): returnfalseto skip an entry. Arguments:true,$action.
Testing mode (Pro)
snipfire_viewer_sees_tests(filter): whether the current visitor sees snippets in testing mode. Default: users who can edit snippets.
Building an add-on
| Hook | Kind | For |
|---|---|---|
snipfire_boot( Plugin ) |
action | Register add-on features, before any snippet runs |
snipfire_supports_{feature} |
filter (bool) | Declare a feature: testing, consent, scss, activity, hook_finder, team, git |
snipfire_css_compiler |
filter (callable) | Compile SCSS/LESS |
snipfire_viewer_sees_test, snipfire_test_runs_early, snipfire_test_snippet_ran |
filter, filter, action | Testing mode |
snipfire_app_config, snipfire_ui_schema |
filters | What the editor app receives |
snipfire_before_app_script |
action | Enqueue scripts before the editor app |
snipfire_tools_sections |
action | Add a section to the Tools page |
snipfire_classic_fields( $snippet ) |
action | Add fields to the classic editor |
Snipfire runs snippets while plugins are still loading, so it loads active plugins named snipfire-* itself, before running snippets, and fires snipfire_boot. Name your add-on's folder snipfire-something to be loaded that early.
REST routes of add-ons can use Snipfire\Rest\Controller::permission( 'view' | 'design' | 'full' ) as their permission callback. The editor app's JavaScript extension points are in Editor app extensions.
Something unclear or missing? Tell us