Block Registration in GT ACF Blocks

  • JNext lesson
  • KPrevious lesson
  • FSearch lessons
  • EscClear search

How Blocks Are Discovered

Flowchart of GT ACF Blocks block discovery on acf/init: manifest read when present, fallback scan of the blocks directory, then per-block registration, field group loading, and extra.php include

On the acf/init hook (priority 5), the function acf_blocks_load_blocks() reads block definitions from a generated manifest (includes/generated-block-manifest.php). The manifest is an OPcache-friendly PHP array of every block’s metadata and field groups, so production requests skip directory scans and JSON decoding entirely. When the manifest is missing, a filesystem scan of blocks/ takes over as a fallback. For each block, three things happen:

ACF block registration here is automatic: on acf/init at priority 5, the loader registers every block in the manifest (or, without a manifest, every folder with a valid block.json). No manual registration list to maintain. Blocks you disable through the Block Manager are skipped along with their field groups and editor assets.

  1. The block is registered with WordPress via register_block_type().
  2. ACF field groups are loaded from JSON files in the same directory.
  3. An extra.php file 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 with acf/. This is the block’s unique identifier.
  • category – Set to acf-blocks so 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 to 3 for ACF Block v3 behavior.
  • supports.jsx – When true, the block supports InnerBlocks.
  • supports.mode – When true, 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 as style).

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.

Seven blocks include extra.php:

  • star-rating-block – Registers the frontend rating script, the acf-blocks/v1/ratings REST route, and the legacy AJAX fallback for saving ratings.
  • post-display – Optimizes the ACF relationship field query for better performance.
  • section-block – Registers an editor-only script with a custom InnerBlocks component and the footer output for per-instance CSS.
  • toc-block – Adds heading ID attributes to post content.
  • url-preview – Registers the admin AJAX handlers for fetching URL metadata and importing images.
  • email-form – Registers the email-form-proxy/v1/submit REST route that relays webhook submissions server-side (browsers block cross-origin webhook POSTs).
  • product-box – Registers the product-box-image (550×550) and product-box-wide (800×450) image sizes.

Adding a New Block

To add a new block:

  1. Create a new directory under blocks/ (e.g. blocks/my-block/).
  2. Add a block.json with the required metadata.
  3. Add a block-data.json with the ACF field group definition.
  4. Create the render template (e.g. my-block.php).
  5. Optionally add a CSS file and reference it in block.json.
  6. Optionally add an extra.php for additional hooks.

One caveat since 2.9.0: when the generated manifest is present, the loader trusts it and won’t see a new folder. Delete includes/generated-block-manifest.php (the loader falls back to scanning blocks/) or regenerate the manifest from the repo’s build tooling, and the block is registered on the next page load. No changes to any other file are needed.

Quick answers to common questions:

How does block auto-discovery work?

acf_blocks_load_blocks() reads the generated block manifest and registers each entry with register_block_type(), loading the matching field groups. Without a manifest it falls back to globbing blocks/ for subdirectories with block.json, so a new folder with valid files still becomes a block on the next page load.

Can I disable specific blocks I don’t use?

Yes. The Performance & Block Manager card (Settings > ACF Blocks License) lets you disable blocks with checkboxes; disabled blocks skip registration, field groups, and editor assets. In code, use the acf_blocks_disabled_blocks filter. Unused blocks cost nothing on the frontend anyway; assets enqueue only when a block renders.