{"id":343064,"date":"2026-07-21T13:40:04","date_gmt":"2026-07-21T13:40:04","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/cache-tags-for-cloudflare\/"},"modified":"2026-07-22T12:15:41","modified_gmt":"2026-07-22T12:15:41","slug":"cache-tags-for-cloudflare","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/cache-tags-for-cloudflare\/","author":3803,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.4.1","stable_tag":"1.4.1","tested":"7.0.2","requires":"6.8","requires_php":"8.3","requires_plugins":null,"header_name":"Cache Tags for Cloudflare","header_author":"Per S\u00f8derlind","header_description":"Adds Cache-Tag HTTP response headers for singular WordPress content and purges Cloudflare by tag when content changes.","assets_banners_color":"cdc9c7","last_updated":"2026-07-22 12:15:41","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/soderlind\/cache-tags-for-cloudflare","header_author_uri":"https:\/\/soderlind.no","rating":0,"author_block_rating":0,"active_installs":0,"downloads":113,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.3.0":{"tag":"1.3.0","author":"PerS","date":"2026-07-21 17:13:34"},"1.3.1":{"tag":"1.3.1","author":"PerS","date":"2026-07-21 20:10:23"},"1.4.0":{"tag":"1.4.0","author":"PerS","date":"2026-07-22 09:48:29"},"1.4.1":{"tag":"1.4.1","author":"PerS","date":"2026-07-22 12:15:41"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon.svg":{"filename":"icon.svg","revision":3617236,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3617236,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3617236,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.3.0","1.3.1","1.4.0","1.4.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3618385,"resolution":"1","location":"assets","locale":"","width":2356,"height":1228},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3618385,"resolution":"2","location":"assets","locale":"","width":2356,"height":1228}},"screenshots":{"1":"Purge tab: purge by post type, taxonomy term, everything, or raw tags.","2":"Settings tab: add Cloudflare API token and Zone ID, enable auto-purge, and verify credentials."}},"plugin_section":[],"plugin_tags":[146,272651,3863,3882,7914],"plugin_category":[52,59],"plugin_contributors":[78884],"plugin_business_model":[],"class_list":["post-343064","plugin","type-plugin","status-publish","hentry","plugin_tags-cache","plugin_tags-cache-tag","plugin_tags-cdn","plugin_tags-cloudflare","plugin_tags-purge","plugin_category-performance","plugin_category-utilities-and-tools","plugin_contributors-pers","plugin_committers-pers"],"banners":{"banner":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/banner-772x250.png?rev=3617236","banner_2x":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/banner-1544x500.png?rev=3617236","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/icon.svg?rev=3617236","icon":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/icon.svg?rev=3617236","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/screenshot-1.png?rev=3618385","caption":"Purge tab: purge by post type, taxonomy term, everything, or raw tags."},{"src":"https:\/\/ps.w.org\/cache-tags-for-cloudflare\/assets\/screenshot-2.png?rev=3618385","caption":"Settings tab: add Cloudflare API token and Zone ID, enable auto-purge, and verify credentials."}],"raw_content":"<!--section=description-->\n<p>Cache Tags for Cloudflare does two things:<\/p>\n\n<ol>\n<li><strong>Tagging<\/strong> \u2014 adds a <code>Cache-Tag<\/code> HTTP response header to singular posts, pages, custom post types and taxonomy terms so Cloudflare can invalidate them by tag.<\/li>\n<li><strong>Purging<\/strong> \u2014 calls the Cloudflare API to purge the relevant tags when content changes (post publish\/update\/trash\/delete and taxonomy term edits).<\/li>\n<\/ol>\n\n<p>The two features can be enabled independently.<\/p>\n\n<p><strong>Works on any Cloudflare plan.<\/strong> The <code>Cache-Tag<\/code> header and purge-by-tag are available on all Cloudflare plans (Free, Pro, Business, and Enterprise); purge API rate limits scale with your plan.<\/p>\n\n<h4>Default tags<\/h4>\n\n<p>For singular content the plugin emits:<\/p>\n\n<ul>\n<li><code>content<\/code><\/li>\n<li><code>b{id}<\/code> (site scope: <code>b1<\/code> on single site, <code>b{blog_id}<\/code> on multisite)<\/li>\n<li><code>b{id}-p{ID}<\/code><\/li>\n<li><code>b{id}-pt-{post_type}<\/code><\/li>\n<li><code>b{id}-t{term_id}<\/code> for every public taxonomy term the post belongs to<\/li>\n<\/ul>\n\n<p>Example header:<\/p>\n\n<pre><code>Cache-Tag: content,b1,b1-p42,b1-pt-post,b1-t5\n<\/code><\/pre>\n\n<p>Term tags use the numeric term ID (<code>b1-t5<\/code>), so they stay stable when a term is renamed or its slug changes.<\/p>\n\n<h4>Credentials<\/h4>\n\n<p>Provide a scoped Cloudflare API token (Zone \u2192 Cache Purge permission) and a Zone ID. Define them in <code>wp-config.php<\/code> for best security:<\/p>\n\n<pre><code>define( 'CACHE_TAGS_CF_API_TOKEN', 'your-scoped-token' );\ndefine( 'CACHE_TAGS_CF_ZONE_ID', 'your-zone-id' );\n<\/code><\/pre>\n\n<p>When these constants are defined they take precedence and the settings fields become read-only. Otherwise enter them under <strong>Settings \u2192 Cache Tags<\/strong>.<\/p>\n\n<h4>Purge tools<\/h4>\n\n<p>The <strong>Settings \u2192 Cache Tags<\/strong> screen has a <strong>Purge<\/strong> tab for manual, on-demand purges by group: a whole post type, a taxonomy term, everything, or raw comma-separated tags. Saving valid credentials on the <strong>Settings<\/strong> tab automatically verifies the Cloudflare connection and unlocks the purge tools.<\/p>\n\n<h4>Automatic purging<\/h4>\n\n<p>When <strong>Auto-purge on changes<\/strong> is enabled and valid credentials are set, the plugin purges the affected tags automatically on these events:<\/p>\n\n<ul>\n<li>Post published, updated, trashed, or untrashed (any transition to or from the published status) \u2014 purges <code>b{id}-p{ID}<\/code> plus the post's <code>b{id}-t{term_id}<\/code> tags.<\/li>\n<li>Post permanently deleted \u2014 purges <code>b{id}-p{ID}<\/code> and its <code>b{id}-t{term_id}<\/code> tags.<\/li>\n<li>Taxonomy term edited or deleted \u2014 purges <code>b{id}-t{term_id}<\/code>.<\/li>\n<\/ul>\n\n<p>Only public post types and taxonomies are considered; revisions and autosaves are ignored. Tags collected during a request are de-duplicated and sent as a single batched purge after the response (in Cloudflare's 30-tags-per-request batches). Draft-only edits, comments, menu\/widget\/theme changes, and plugin\/core updates do not trigger a purge \u2014 use the Purge tab, WP-CLI, or the <code>cache_tags_for_cloudflare\/purge_tags<\/code> filter for those. Static files such as images are served outside WordPress and are not tagged or purged by tag.<\/p>\n\n<h4>Hooks and programmatic purging<\/h4>\n\n<p>The plugin exposes hooks for customizing tags and purging from your own code:<\/p>\n\n<ul>\n<li>Filters: <code>cache_tags_for_cloudflare\/tags<\/code>, <code>cache_tags_for_cloudflare\/purge_tags<\/code><\/li>\n<li>Result actions: <code>cache_tags_for_cloudflare\/purged<\/code>, <code>cache_tags_for_cloudflare\/purge_failed<\/code><\/li>\n<li>Programmatic purging: <code>cache_tags_for_cloudflare\/purge_post<\/code>, <code>\/purge_terms<\/code>, <code>\/purge_post_type<\/code>, <code>\/purge_all<\/code>, <code>\/purge<\/code><\/li>\n<\/ul>\n\n<p>See the <a href=\"https:\/\/github.com\/soderlind\/cache-tags-for-cloudflare\/blob\/main\/docs\/DEVELOPER.md\">Developer guide<\/a> for full documentation and examples.<\/p>\n\n<h4>WP-CLI<\/h4>\n\n<pre><code>wp cache-tags purge --post-type=page\nwp cache-tags purge --taxonomy=category --terms=news,sport\nwp cache-tags purge --post=42\nwp cache-tags purge --tags=b1-t5,content\nwp cache-tags purge --all\nwp cache-tags verify\n<\/code><\/pre>\n\n<p>On multisite, <code>--all<\/code> purges only the current subsite (via its <code>b{id}<\/code> tag). To purge every site sharing the Cloudflare zone at once, purge the global <code>content<\/code> tag: <code>wp cache-tags purge --tags=content<\/code>.<\/p>\n\n<h4>External services<\/h4>\n\n<p>This plugin connects to the <strong>Cloudflare API<\/strong> (<code>https:\/\/api.cloudflare.com<\/code>) to verify your credentials and to purge cached content by cache tag. Cloudflare is required for the plugin's purging feature to work; the tagging feature (emitting <code>Cache-Tag<\/code> headers) works without contacting any external service.<\/p>\n\n<p>The plugin contacts Cloudflare in the following cases, and only after you have provided a Cloudflare API token and Zone ID:<\/p>\n\n<ul>\n<li><strong>Verifying credentials<\/strong> \u2014 when you save credentials on the settings screen or run <code>wp cache-tags verify<\/code>, the plugin calls <code>GET https:\/\/api.cloudflare.com\/client\/v4\/user\/tokens\/verify<\/code>. It sends your API token (in the <code>Authorization<\/code> header) so Cloudflare can confirm the token is valid.<\/li>\n<li><strong>Purging cache<\/strong> \u2014 when content changes and auto-purge is enabled, or when you purge manually via the settings screen or <code>wp cache-tags purge<\/code>, the plugin calls <code>POST https:\/\/api.cloudflare.com\/client\/v4\/zones\/{zone-id}\/purge_cache<\/code>. It sends your API token (in the <code>Authorization<\/code> header), your Zone ID (in the request URL), and the list of cache tags to purge (in the request body). It does not send post content, personal data, or visitor information.<\/li>\n<\/ul>\n\n<p>No data is sent to Cloudflare until you configure credentials, and no request is made unless one of the actions above is triggered.<\/p>\n\n<p>Cloudflare is a third-party service provided by Cloudflare, Inc. By using this plugin's purging feature you agree to Cloudflare's terms and privacy policy:<\/p>\n\n<ul>\n<li>Terms of Service: https:\/\/www.cloudflare.com\/website-terms\/<\/li>\n<li>Privacy Policy: https:\/\/www.cloudflare.com\/privacypolicy\/<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>\/wp-content\/plugins\/cache-tags-for-cloudflare<\/code> or install it from the Plugins screen.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Go to <strong>Settings \u2192 Cache Tags<\/strong> and add your Cloudflare API token and Zone ID (or define the constants in <code>wp-config.php<\/code>).<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20get%20a%20cloudflare%20api%20token%20and%20zone%20id%3F\"><h3>How do I get a Cloudflare API token and Zone ID?<\/h3><\/dt>\n<dd><p>In the Cloudflare dashboard, create a scoped API token (<strong>My Profile \u2192 API Tokens \u2192 Create Token<\/strong>) with the <strong>Zone \u2192 Cache Purge<\/strong> permission, limited to the zone you want to purge. Your Zone ID is on that zone's <strong>Overview<\/strong> page. Add both under <strong>Settings \u2192 Cache Tags<\/strong>, or define <code>CACHE_TAGS_CF_API_TOKEN<\/code> and <code>CACHE_TAGS_CF_ZONE_ID<\/code> in <code>wp-config.php<\/code>.<\/p><\/dd>\n<dt id=\"do%20i%20need%20to%20configure%20anything%20in%20cloudflare%3F\"><h3>Do I need to configure anything in Cloudflare?<\/h3><\/dt>\n<dd><p>No extra setup is required. Cloudflare reads the <code>Cache-Tag<\/code> header the plugin adds automatically, and the plugin purges by tag through the API. Just make sure your site is proxied through Cloudflare (orange-clouded) so responses are cached.<\/p><\/dd>\n<dt id=\"why%20don%27t%20i%20see%20the%20cache-tag%20header%20on%20my%20live%20site%3F\"><h3>Why don't I see the Cache-Tag header on my live site?<\/h3><\/dt>\n<dd><p>When traffic is proxied through Cloudflare, Cloudflare consumes the <code>Cache-Tag<\/code> header and strips it before the response reaches visitors. Check it at the origin instead: <code>curl -I https:\/\/example.com\/sample-post\/<\/code>.<\/p><\/dd>\n<dt id=\"why%20isn%27t%20my%20content%20being%20purged%20automatically%3F\"><h3>Why isn't my content being purged automatically?<\/h3><\/dt>\n<dd><p>Auto-purge only runs when <strong>Auto-purge on changes<\/strong> is enabled and valid credentials are saved and verified. It also only fires for public post types\/taxonomies on real content changes \u2014 draft-only edits, comments, menu\/widget\/theme changes, and plugin\/core updates are ignored. For those, use the Purge tab, WP-CLI, or a purge hook. Enable debug logging on the Settings tab to see what was purged.<\/p><\/dd>\n<dt id=\"can%20i%20purge%20manually%20or%20from%20my%20own%20code%3F\"><h3>Can I purge manually or from my own code?<\/h3><\/dt>\n<dd><p>Yes. Use the <strong>Purge<\/strong> tab (by post type, taxonomy term, everything, or raw tags), the <code>wp cache-tags purge<\/code> WP-CLI command, or the programmatic purge hooks (<code>cache_tags_for_cloudflare\/purge_post<\/code>, <code>\/purge_terms<\/code>, <code>\/purge_all<\/code>, and more). See the <a href=\"https:\/\/github.com\/soderlind\/cache-tags-for-cloudflare\/blob\/main\/docs\/DEVELOPER.md\">Developer guide<\/a>.<\/p><\/dd>\n<dt id=\"does%20it%20work%20on%20multisite%3F\"><h3>Does it work on multisite?<\/h3><\/dt>\n<dd><p>Yes. Every tag is scoped to the current blog (<code>b{blog_id}<\/code>), so purges on one subsite never affect another. Each subsite uses its own Cloudflare credentials. \"Purge everything\" (the Purge tab, <code>--all<\/code>, or <code>purge_all<\/code>) is also scoped to the current subsite; to purge every site sharing the same Cloudflare zone at once, purge the global <code>content<\/code> tag with <code>wp cache-tags purge --tags=content<\/code>.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20send%20any%20personal%20or%20content%20data%20to%20cloudflare%3F\"><h3>Does the plugin send any personal or content data to Cloudflare?<\/h3><\/dt>\n<dd><p>No. Requests to Cloudflare contain only your API token, Zone ID, and the list of cache tags to purge \u2014 never post content, personal data, or visitor information. See the <strong>External services<\/strong> section above for the exact endpoints.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.4.1<\/h4>\n\n<ul>\n<li>Changed: The purge-failure admin notice now links to the Cache Tags settings page so credentials can be fixed in one click.<\/li>\n<li>Changed: Added WordPress.org as the primary install option in the README.<\/li>\n<li>Security: Bumped <code>fast-uri<\/code> to 3.1.4 to resolve a high-severity advisory (build-only dependency; nothing ships in the plugin).<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Added: Purge by URL. When a post is published (including a draft or scheduled post going live), its permalink is now purged by URL alongside its cache tags. This invalidates responses that carry no cache tag \u2014 most importantly a cached <code>404<\/code> at a URL that has since become a real post \u2014 which tag-based purging alone cannot reach.<\/li>\n<li>Added: <code>cache_tags_for_cloudflare\/purge_urls<\/code> action hook to purge arbitrary URLs programmatically.<\/li>\n<li>Added: <code>wp cache-tags purge --urls=&lt;urls&gt;<\/code> WP-CLI flag (comma-separated URLs).<\/li>\n<li>Added: <code>cache_tags_for_cloudflare\/purged_urls<\/code> and <code>cache_tags_for_cloudflare\/purge_urls_failed<\/code> hooks fired after an automatic URL purge. URL purges are sent as a separate Cloudflare request from tag purges and must match the cached request exactly (scheme, host, trailing slash, query).<\/li>\n<\/ul>\n\n<h4>1.3.1<\/h4>\n\n<ul>\n<li>Fixed: \"Purge everything\" (the Purge tab, <code>wp cache-tags purge --all<\/code>, and the <code>cache_tags_for_cloudflare\/purge_all<\/code> hook) now purges the blog-scoped <code>b{id}<\/code> tag instead of the shared <code>content<\/code> tag. On multisite this keeps the purge scoped to the current subsite instead of clearing every site sharing the Cloudflare zone. To purge every site in the zone at once, purge the <code>content<\/code> tag directly (e.g. <code>wp cache-tags purge --tags=content<\/code>).<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Taxonomy cache tags now use the numeric term ID: <code>b{id}-t{term_id}<\/code> (e.g. <code>b1-t5<\/code>) instead of <code>b{id}-{taxonomy}-{slug}<\/code>. Shorter and stable across term renames and slug changes.<\/li>\n<li>Added programmatic purging via action hooks: <code>cache_tags_for_cloudflare\/purge_post_type<\/code>, <code>\/purge_terms<\/code>, <code>\/purge_post<\/code>, <code>\/purge_all<\/code>, and <code>\/purge<\/code> (raw tags). These purge immediately.<\/li>\n<li>Added structured WP-CLI flags: <code>--post-type<\/code>, <code>--taxonomy<\/code> with <code>--terms<\/code>, and <code>--post<\/code>, alongside the existing <code>--tags<\/code> and <code>--all<\/code>.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>Shortened the cache-tag vocabulary and scoped every tag to the blog. Tags are now <code>content<\/code>, <code>b{id}<\/code>, <code>b{id}-p{ID}<\/code>, <code>b{id}-pt-{post_type}<\/code>, and <code>b{id}-{taxonomy}-{slug}<\/code> (e.g. <code>b1-p42<\/code>, <code>b1-category-news<\/code>). On multisite the current blog ID is used; single sites use <code>b1<\/code>. Replaces the previous <code>post-id-<\/code>, <code>post-type-<\/code>, <code>{taxonomy}-<\/code>, and <code>site-id-<\/code> tags.<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Fixed alignment of the Purge buttons on the settings page.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Rebuilt the settings screen as a React app with Purge and Settings tabs.<\/li>\n<li>Added purge-by-group: whole post type, taxonomy term, everything, and raw tags.<\/li>\n<li>Added a REST API (cache-tags-for-cloudflare\/v1) backing the admin UI.<\/li>\n<li>Purging is locked until valid credentials are saved and verified; saving auto-verifies the connection.<\/li>\n<li>Added a Vitest JavaScript test suite.<\/li>\n<li>Made the plugin installable via Composer (composer require).<\/li>\n<li>Corrected docs: works on all Cloudflare plans (not Enterprise-only).<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: Cache-Tag headers for singular content plus Cloudflare purge-by-tag on content changes.<\/li>\n<\/ul>","raw_excerpt":"Precise Cloudflare cache purging for WordPress: adds Cache-Tag headers and purges only affected posts, pages, and terms.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/343064","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=343064"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/pers"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=343064"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=343064"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=343064"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=343064"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=343064"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=343064"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}