Storage, data format and constants
File storage
Snippets are files, not database rows:
wp-content/snipfire/
index.php compiled index: every snippet's settings (no code)
index.token freshness check for the index
snippets/
12-3f9a1c.php PHP and HTML snippets, with an ABSPATH guard on line 1
15-b27e04.css CSS source (SCSS/LESS source for Pro stylesheets)
18-9c1d55.js JavaScript source
revisions/12/… history, one guarded file per version
activity/2026-09.php activity log (Pro), one file per month
wp-content/uploads/snipfire/
15.css, 18.js compiled, public CSS/JS for snippets
- Loading snippets costs no database queries. Each request includes
index.phponce, which OPcache serves from memory, and hooks in the active snippets. - Cache-safe. Code files get a new name whenever their content changes, and the index is checked against
index.token(read without OPcache). Edits from WP-CLI, another server, or hosts withopcache.validate_timestamps=0take effect on the next request. - Written safely. The index is written to a temporary file and renamed, under a lock.
- Protected. Every folder has an
index.php, an.htaccess(Require all denied) and aweb.config. PHP files start withdefined( 'ABSPATH' ) || exit;, placed on line 1 together with your first line so error line numbers match the editor. - Multisite. Each site after the first uses
wp-content/snipfire/site-{id}/.
Don't edit these files by hand: use the editor, WP-CLI, the REST API or Git sync.
Snippet fields
As used by the REST API, WP-CLI (get --format=json) and exports:
| Field | Values |
|---|---|
id |
Number on this site |
uid |
Permanent ID that travels with the snippet (exports, Git). Set once, never changes. Library snippets have sflib- and their short name; the Header & Footer boxes have fixed uids |
title, description |
Text |
type |
php, html, css, js |
lang |
CSS snippets: css, scss, less (empty for other types) |
code |
The code |
status |
active or inactive |
mode |
live or test (testing mode) |
run |
auto, shortcode or manual (CSS and JS are always auto) |
hook |
The location: see Location keys |
priority |
Number, default 10 |
position |
HTML snippets on a location that takes a number: which paragraph, or which post in the list (1 to 1000, default 1). See Where snippets run |
shortcode |
Custom shortcode tag |
conditions |
See Conditions as JSON |
load_as |
CSS/JS: inline or file |
js_strategy |
JS files: "", defer or async |
consent |
JS/HTML: "", statistics, marketing, preferences, functional |
tags |
List of strings |
folder |
Folder/Subfolder, "" for none |
deps |
SCSS/LESS: IDs of the partials it uses (read-only) |
error |
The last runtime error that switched it off, or null (read-only) |
author, modified_by, created, modified |
User IDs and Unix timestamps (read-only) |
Location keys
The hook value for each location in the editor:
| Type | Keys |
|---|---|
| PHP | root (Run immediately), plugins_loaded, after_setup_theme, init, wp_loaded, admin_init, wp, template_redirect, wp_head, wp_body_open, wp_footer, admin_head, admin_footer, or any action name |
| HTML | wp_head, wp_body_open, wp_footer, the_content:before, the_content:after, the_content:paragraph_before, the_content:paragraph_after, the_excerpt:before, the_excerpt:after, archive:before_post, archive:after_post, archive:between_posts, admin_head, admin_footer, login_head, login_footer, or any action name |
| CSS | frontend, frontend_editor, editor, admin, login |
| JS | frontend_footer, frontend_head, admin_footer, admin_head, login |
Defaults: PHP root, HTML wp_footer, CSS frontend, JS frontend_footer.
The HTML locations the_content:paragraph_before, the_content:paragraph_after, archive:before_post and archive:after_post use the snippet's position field for the paragraph or post number.
Conditions as JSON
A list of groups; each group is a list of rules. The snippet runs when any group matches, and a group matches when all its rules do. An empty list means "always".
[
[
{ "type": "user_logged_in", "op": "is_not", "value": null },
{ "type": "page_type", "op": "is", "value": ["wc_shop"] }
],
[
{ "type": "query_param", "op": "equals", "value": { "key": "utm_source", "value": "facebook" } }
]
]
wp snipfire update 12 --conditions='[[{"type":"environment","op":"is","value":["production"]}]]'
type |
op |
value |
|---|---|---|
location (Request type) |
is, is_not |
list of frontend, admin, login, rest, ajax, cron |
user_logged_in |
is, is_not |
null |
user_role |
is, is_not |
list of role keys (administrator, customer…) |
url |
contains, not_contains, equals, not_equals, starts_with, regex |
string |
query_param, cookie |
exists, not_exists, equals, not_equals, contains |
{ "key": "…", "value": "…" } |
device |
is, is_not |
list of mobile, desktop |
page_type |
is, is_not |
list of front_page, blog, singular, single, page, attachment, archive, category, tag, taxonomy, author, date, search, 404, wc_shop, wc_product, wc_product_category, wc_cart, wc_checkout, wc_account, wc_thankyou |
post_type |
is, is_not |
list of post type keys |
post_id |
is, is_not |
list of IDs |
term |
is, is_not |
list of taxonomy:slug |
date_range |
is, is_not |
{ "from": "2026-11-27 00:00", "to": "2026-11-30" } (either may be empty) |
time_of_day |
is, is_not |
{ "from": "22:00", "to": "06:00" } |
day_of_week |
is, is_not |
list of 1 (Monday) … 7 (Sunday), as strings |
environment |
is, is_not |
list of production, staging, development, local |
plugin_active |
is, is_not |
list of plugin folder names |
referrer Pro |
as url |
string |
country Pro |
is, is_not |
list of two-letter codes |
region Pro |
is, is_not |
list of eu, eea, gdpr, africa, antarctica, asia, europe, north_america, oceania, south_america |
consent Pro |
includes, excludes |
list of statistics, marketing, preferences, functional |
language Pro |
is, is_not |
list of language codes (as listed by GET /schema) |
wc_cart_total, wc_cart_count, wc_order_count Pro |
at_least, less_than, equals |
number as a string ("49.99") |
wc_cart_product, wc_bought Pro |
includes, excludes |
list of product IDs |
wc_cart_category Pro |
includes, excludes |
list of category slugs |
Values that don't fit a rule are cleaned to the expected shape when the snippet is saved. Rule types that aren't registered (for example Pro rules while Snipfire Pro is inactive) are kept as they are and never match. GET /schema returns the list of available types with labels and options.
Export format
{
"format": "snipfire",
"version": 1,
"generator": "Snipfire 0.15.0",
"exported": "2026-09-24T10:00:00+00:00",
"snippets": [
{ "uid": "…", "title": "…", "type": "php", "code": "…", "hook": "root", "status": "active", "…": "…" }
]
}
Each snippet has the snippet fields except hash, error and author. On import, IDs, compiled data and errors are ignored, and every snippet is created as new (switched off unless you ask to keep the status). Files without "format": "snipfire" are refused.
Constants
Add these to wp-config.php, above That's all, stop editing!.
| Constant | Effect |
|---|---|
define( 'SNIPFIRE_SAFE_MODE', true ); |
No snippet runs for anyone. See Safe mode |
define( 'SNIPFIRE_DISABLE_PHP', true ); |
No PHP runs from Snipfire, for anyone: PHP snippets and HTML snippets containing PHP stay off and can't be switched on or run. HTML, CSS and JavaScript keep working. See Locking Snipfire down |
define( 'DISALLOW_UNFILTERED_HTML', true ); |
A WordPress constant. Snipfire becomes view only for everyone signed in; snippets that are on keep running, and WP-CLI still works. See Locking Snipfire down |
define( 'SNIPFIRE_DELETE_DATA', true ); |
Deleting the plugin also deletes the snippet files, history, activity log and compiled CSS/JS. Without it, they're kept |
define( 'SNIPFIRE_STORAGE_DIR', '/path/to/folder' ); |
Store snippets somewhere other than wp-content/snipfire (must be writable by the web server; ideally outside the web root) |
define( 'SNIPFIRE_GIT_TOKEN', '…' ); |
The Git sync access token, kept out of the database (Agency) |
If you set SNIPFIRE_STORAGE_DIR on a site that already has snippets, move the contents of the old folder there first.
Something unclear or missing? Tell us