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
runs/12.php run log of a scheduled snippet (Pro), the last 50 runs
profile/2026-09-27.php snippet performance measurements (Pro), one file per day, kept a week
network/… network snippets (Pro, multisite): index, code, history, activity
wp-content/uploads/snipfire/
15.css, 18.js compiled, public CSS/JS for snippets
wp-content/uploads/snipfire-network/
network snippets' CSS/JS (Pro, multisite; the main site's uploads)
- 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}/. Deleting a site deletes its folder. Network snippets live in the main folder'snetwork/.
Don't edit these files by hand: use the editor, WP-CLI, the REST API or Git sync.
Page code for a single post or page isn't a snippet: it's saved with the post, in the post meta field _snipfire_page_scripts (head, body, footer, skip_global).
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, manual, or schedule (PHP only, runs with Pro). CSS and JS are always auto |
schedule |
For run schedule: { "every": "hourly" \| "twicedaily" \| "daily" \| "weekly" \| "minutes", "minutes": 15, "start": 1790000000 }. minutes 5 to 10080 (for minutes); start a Unix time, or a date and time in the site's time zone such as "2026-10-01 03:00" (0 = one interval after switching on). Empty for other snippets. See Scheduled snippets |
hook |
The location: see Location keys |
selector |
For hook element:selector (HTML, placed by Pro): { "css": "#main h2", "insert": "before" \| "after" \| "start" \| "end" \| "replace", "match": 1 }. match 1 is the first matching element, 2 the second…, 0 all of them. A plain string is taken as css. Empty for other snippets. See Next to an element |
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 |
smart_tags |
HTML/JS: true to replace smart tags such as {post_title} (always false for other types) |
fields |
The settings form: a list of fields, see Settings form fields. [] for none |
values |
The form's values, by field key. On an update, only the keys you send change; send values_mode: "replace" (CLI --replace-values) to replace them all, so fields left out go back to their default |
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) |
Settings form fields
Each field in fields:
| Key | Values |
|---|---|
key |
Lowercase letters, numbers and _, starting with a letter, up to 40 characters. Unique in the snippet |
label |
Text shown on the form |
type |
text, textarea, number, toggle, select, checkboxes, color, url, email, repeater |
help, placeholder |
Optional text |
default |
Optional. The value when none is set |
options |
select and checkboxes: [ { "value": "…", "label": "…" } ], or { "value": "Label" }, or [ "a", "b" ] |
min, max, step |
number: optional |
fields |
repeater: the columns, as fields of type text, textarea, number, url, email or toggle |
Up to 50 fields per snippet. Fields that don't fit these rules are dropped when the snippet is saved.
{
"fields": [
{ "key": "accent", "label": "Accent colour", "type": "color", "default": "#f60" },
{ "key": "size", "label": "Size", "type": "select", "options": { "s": "Small", "l": "Large" }, "default": "s" },
{ "key": "links", "label": "Links", "type": "repeater", "fields": [
{ "key": "text", "label": "Text", "type": "text" },
{ "key": "url", "label": "Address", "type": "url" }
] }
],
"values": { "accent": "#09c", "size": "l", "links": [ { "text": "Shop", "url": "/shop/" } ] }
}
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, element:selector (Pro, with the selector field), 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), for example el, pt-br |
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 |
php_code Pro |
is, is_not |
a PHP expression as a string, up to 4,000 characters (full access only) |
site Agency |
is, is_not |
list of site IDs as strings (["2","3"]): the Site of the network rule, for network snippets on multisite |
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.17.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, administrators keep Tools & Safe Mode (safe mode, system info), 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, run logs, performance data, compiled CSS/JS and the page code saved with posts (on every site of a network). Deleting Snipfire Pro with it also deletes the secrets and network snippets' 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_DISABLE_UPDATE_CHECK', true ); |
Snipfire doesn't check snipfirewp.com for new versions. Update by uploading the zip. See Updating Snipfire |
define( 'SNIPFIRE_UPDATE_URL', 'https://…/snipfire.zip' ); |
Get updates from another server, for example a staging build. Must be https:// (plain http:// only on local and development sites). The signature must be at the same address plus .sig, and match Snipfire's built-in release keys: see Signed updates |
define( 'SNIPFIRE_UPDATE_TEST_KEYS', '…' ); |
For Snipfire's own development: extra trusted release keys (base64 public keys), honoured only when WP_ENVIRONMENT_TYPE is local or development |
define( 'SNIPFIRE_SECRETS_KEY', '…' ); |
The encryption key of the secrets vault (Pro) and the agency hub's stored passwords: at least 32 random characters. Without it, a key made from the site's salts is used |
define( 'SNIPFIRE_NETWORK_SAFE_MODE', true ); |
No network snippet runs on any site of the network (Agency, multisite). The sites' own snippets keep running |
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