Skip to content

Early-bird lifetime licence: $199 once, for the first 200 buyers only. See the offer

All docs

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.php once, 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 with opcache.validate_timestamps=0 take 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 a web.config. PHP files start with defined( '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