Crocoblock is the data engine that makes WordPress AI-buildable. This is our working reference — distilled from a six-volume internal research series and verified against live installations. It is a map of what actually works in mid-2026, including the traps that cost days.
The architectural backbone
The single most important decision when automating a Crocoblock site is this: separate the template from the data.
Build and sign one template per template type — once. From then on, create only data records (JetEngine CCT items via REST). Each record renders automatically through the already-signed template.
Why it matters: this keeps template signing out of the per-article path. In Oxygen Classic, signing is the only genuinely autonomy-blocking step. Get this wrong and every published article requires a human. Get it right and publishing is a single REST call. [V]
Choosing the build engine (the finding most people get wrong)
Crocoblock has no native Oxygen integration. Not Oxygen Classic 4.x, not Oxygen 6. JetEngine is natively supported only in Elementor, Gutenberg, Bricks, and — since roughly March 2026 — Divi 5. Oxygen 6’s native Dynamic Data lists only ACF and Meta Box. [V]
This surprises people who assume “page builder + Crocoblock” is a solved combination. It is not.
Decision tree
| Site type | Choose | Why |
|---|---|---|
| Data-driven (directory, catalog, listings, map/radius search) | Bricks + JetEngine | Clean markup, strong Core Web Vitals, full native JetEngine support |
| Design-led marketing site (few data types) | Oxygen 6 + ACF / Meta Box | Native dynamic data, no signing step |
| Locked to Oxygen but need JetEngine data | Oxygen as a pure presentation layer | Bridge the data in via shortcodes — never assume native binding |
The shortcode bridge
When you must combine Oxygen with JetEngine, pull data through a Code/Shortcode element:
[jet-engine-listing] <!-- Listing Grid -->
Crocoblock & JetEngine for AI-Built WordPress: A Verified Field Guide <!-- single field -->
[jet_smart_filters ...] <!-- filters -->
[jet_fb_form form_id="X"] <!-- JetFormBuilder -->
Note what does not work: JetThemeCore and JetMenu have neither an Oxygen element nor a shortcode. Use Oxygen-native headers, footers and menus instead. The same is true of most of the visual-element modules (JetTabs, JetElements, JetBlog, JetReviews). JetPopup is the exception — it can be triggered via a custom selector or the jet-popup-open-trigger event. [V]
CPT or CCT? The decision that quietly decides your SEO
This is where teams lose months, so be precise. The two storage models are not interchangeable, and the tempting one is usually wrong.
| Custom Post Type (CPT) | Custom Content Type (CCT) | |
|---|---|---|
| Storage | wp_posts + wp_postmeta |
Dedicated table wp_jet_cct_<slug>, one row per item |
| Individual pages | Native | Only via “Has Single Page” linkage |
| Taxonomies | Native | None — use Relations |
| Archive URLs | Real, rankable archives | Cannot produce them |
| Scales to | Moderate volumes | Large volumes (>1000 rows) |
The rule: if the content is meant to rank, use a CPT with its own taxonomies and JetSmartFilters. That is what gives you genuine archive URLs like /category/<term>/ that search engines can index and that internal linking can point at. CCT cannot produce rankable archives. [V — learned in production, not from the docs]
Reserve CCT for what it is genuinely good at: a high-volume, verified knowledge store — structured rows your pipeline reads and writes, that never need to be indexed as pages of their own.
Choosing CCT because it “scales better” and later discovering your category archives cannot exist is one of the most expensive mistakes in this stack. Decide by what must rank, not by row count.
Field discipline (both models)
Bind on field name, never on label — labels change silently and your data maps to the wrong column. For images, store the Media URL, not the Media ID. A weak field contract produces data that looks fine and is wrong.
Publishing via REST
With Register create item REST API Endpoint enabled on the CCT, publishing becomes one authenticated call:
POST /wp-json/jet-cct/<slug> # CCT rows
POST /wp-json/wp/v2/<rest_base> # CPT posts (use this for rankable content)
Authorization: Basic base64(user:application_password)
Content-Type: application/json
{ "title": "…", "body": "<p>…</p>", "hero_image": "https://…", "slug": "…" }
Field names must match the CCT field slugs exactly, or data maps silently and wrongly. Set Access Capability to edit_posts or a dedicated bot role. Application Passwords require HTTPS and are shown once.
A dead end worth naming: JetEngine ships an MCP server endpoint (/wp-json/jet-engine/v1/mcp/) that looks like an attractive structural build path for AI agents. In practice it is gated by an MCP-protocol approval step — an automated caller receives “no approval received” and cannot proceed. It is not a setting you can switch off. Do not architect around it; use REST with an Application Password. [V — verified against a live install]
The Query ID rule (the filter trap)
Filters that “connect” but never update the listing are almost always one mismatch. A deterministic Query ID must appear in three places, identically:
- the filter’s
query_id - the listing’s
_element_id - the Query Builder query’s Query ID
Use a stable convention such as site-cct-<slug> — letters and hyphens only.
On custom taxonomy archives, reach for the %queried_term% / %current_terms% macros in the Query Builder rather than hard-coding terms. This is what lets one query serve every term archive instead of one query per term. [V]
⚠️ Security floors — check these today
Crocoblock’s 2026 advisories are severe and hit exactly the Listing Grid and CCT REST surfaces that automation depends on. Pin at or above:
| Plugin | Minimum | Issue |
|---|---|---|
| JetEngine | 3.8.6.2 | CVE-2026-4662 — unauthenticated, CVSS 9.3, via Listing Grid filtered_query; and CVE-2026-4352 via the CCT REST _cct_search parameter |
| JetFormBuilder | 3.5.6.2 | CVE-2026-32525 — code injection, CVSS 9.9 |
| JetSmartFilters | 3.8.2.1 | — |
| JetSearch | 3.5.10.1 | CVE-2025-49931 — unauthenticated blind SQLi, CVSS 9.3 |
[V] If you run an automated publishing pipeline against JetEngine below 3.8.6.2, you are exposing the exact endpoints your pipeline uses. Update before you automate.
Common failure modes
- Blank page / “invalid signature” (Oxygen Classic) → re-sign the template.
- Styles vanish on programmatic render → you used ID styling. Move everything to classes. ID-bound CSS does not load via
do_oxygen_elements, and repeaters duplicate IDs per card.[V] - Content is invisible to Google → the body lives in a custom field the theme never renders. Check the raw server HTML, not a rendered preview. This one is silent and total.
[V] - CCT item exists but has no page → it was created before “Has Single Page” was linked. Clone or recreate.
- Filter connects but nothing updates → Query ID does not match
_element_id. - Nordic characters (æøå) corrupt → edit only via the builder or JSON; avoid “Update” in the standard WP editor.
Verify before you publish
Do not rely on an LLM critiquing its own output. Use a two-tier gate, and require both to pass:
Tier 1 — deterministic, no LLM: HTTP 200 after redirects; exactly one <h1>; title 50–60 characters; meta description 70–160; valid JSON-LD; alt text on every content image; content present in the raw server-rendered source (this is what catches an unsigned template rendering blank); correct canonical, robots, viewport, Open Graph.
Tier 2 — a separate LLM judge (a different model than the writer), scored on a rubric: factual grounding, completeness against the brief, structure, keyword relevance without stuffing, tone, originality. Auto-accept only at the top band; route the middle band to human review.
Design floor
8px spacing grid (4px half-steps), modular type scale, 12/8/4-column responsive grid, and WCAG 2.2 AA — contrast 4.5:1 for normal text, focus indicators at least 3:1 and 2px, minimum 24×24px targets, 400% reflow. The European Accessibility Act has applied since 28 June 2025. Design tokens as CSS variables are the source of truth.
Open questions we are still verifying
Honesty matters more than a tidy page. These are flagged [F] — derived, not yet confirmed against a live install:
- Oxygen 6’s internal template/header/footer post-type slugs and global-class JSON key.
- Whether the community
oxygen-clisigning tool works on Oxygen 6.x (tested only through 4.x). - The exact
jet-cctCREATE response payload — does it return_ID? - Whether Crocoblock will ship a Breakdance/Oxygen 6 data provider (suggestion #7180 is still open).
Closed since first publication: the JetEngine MCP server as an agent build path — confirmed a dead end (see above).
This page is part of our WordPress-with-AI research cluster. Deep-dive volumes on JetEngine, JetFormBuilder, JetSmartFilters + JetSearch, JetThemeCore + JetPopup + JetMenu, the visual layer, and the WooCommerce/booking modules follow as linked spokes.
Verified, not asserted. [V] = verified against source. [F] = flagged for live verification.