How Blocks Are Discovered
On the acf/init hook (priority 5), the function acf_blocks_load_blocks() scans the blocks/ directory for subdirectories containing a block.json file. For each valid block directory, three things happen:
- The block is registered with WordPress via
register_block_type(). - ACF field groups are loaded from JSON files in the same directory.
- An
extra.phpfile is included if it exists.
block.json Format
Every block uses ACF Block API v3 with standard WordPress block metadata. Here is a representative example:
{
"apiVersion": 3,
"name": "acf/accordion",
"title": "Accordion",
"description": "A customizable accordion block with FAQ schema support.",
"category": "acf-blocks",
"icon": "list-view",
"keywords": ["accordion", "faq", "toggle"],
"acf": {
"renderTemplate": "accordion-block.php",
"blockVersion": 3
},
"supports": {
"align": ["wide", "full"],
"mode": true,
"jsx": true,
"anchor": true
},
"style": "file:./accordion.css",
"editorStyle": "file:./accordion.css"
}
Key fields:
name– Must start withacf/. This is the block’s unique identifier.category– Set toacf-blocksso the block appears in the ACF Blocks inserter category.acf.renderTemplate– The PHP file used to render the block. Path is relative to the block directory.acf.blockVersion– Set to3for ACF Block v3 behavior.supports.jsx– Whentrue, the block supports InnerBlocks.supports.mode– Whentrue, the block can switch between edit and preview mode.style– Path to the block’s CSS file, loaded on the frontend (conditional) and in the editor.editorStyle– Path to editor-only styles (often the same file asstyle).
Field Group Registration
The function acf_blocks_register_field_groups() scans each block directory for *.json files, skipping block.json. Each JSON file should contain an ACF field group definition with a key and fields array. The function calls acf_add_local_field_group() for each valid group.
Both single group objects and arrays of groups are supported:
{
"key": "group_accordion_fields",
"title": "Accordion",
"fields": [ ... ],
"location": [[
{ "param": "block", "operator": "==", "value": "acf/accordion" }
]],
"active": true
}
The location rule ties the field group to its block. This is standard ACF configuration.
Because field groups are registered with acf_add_local_field_group(), they are “local” to the plugin. They do not appear in the ACF field group admin UI for editing and cannot be accidentally overwritten by database-stored groups.
Style Pre-Registration
On init (priority 5), acf_blocks_register_styles() scans all block directories and calls wp_register_style() for each block’s CSS file. The handle format is {block-name}-style (e.g. acf-accordion-style).
This pre-registration is what enables conditional loading. WordPress automatically enqueues a registered block style only on pages where that block is rendered, rather than loading all 29 stylesheets on every page.
The extra.php File
If a block directory contains an extra.php file, it is require_once‘d during block registration. This file typically registers AJAX handlers, content filters, or additional scripts.
Five blocks include extra.php:
- star-rating-block – Registers the frontend rating submission script and the AJAX handler for saving ratings.
- post-display – Optimizes the ACF relationship field query for better performance.
- section-block – Registers an editor-only script with a custom
InnerBlockscomponent. - toc-block – Adds heading ID attributes to post content and injects scroll-margin CSS.
- url-preview – Registers the admin AJAX handlers for fetching URL metadata and importing images.
Adding a New Block
To add a new block:
- Create a new directory under
blocks/(e.g.blocks/my-block/). - Add a
block.jsonwith the required metadata. - Add a
block-data.jsonwith the ACF field group definition. - Create the render template (e.g.
my-block.php). - Optionally add a CSS file and reference it in
block.json. - Optionally add an
extra.phpfor additional hooks.
The block is automatically registered on the next page load. No changes to any other file are needed.