How Facets Work
Facet runtime is target-centric. Every control identifies a target, and every Facet Target with the same target ID participates in that target scope.
Render and Refresh Lifecycle
- During the original page render,
FacetBlockInterceptordetectsFacet Targetcomponents. - The target's loop and fallback slots are normalized and stored as the refresh template.
- Facet controls register query descriptors for the same target ID.
- On interaction, the client builds scoped facet clauses and calls the facet REST endpoint.
- The endpoint applies those clauses to the target loop config, re-renders the stored target template, computes pagination and availability metadata, and returns markup.
- The client replaces the target content, updates URL state, updates option availability, applies pagination metadata, and reruns returned scripts when the target allows it.
Target ID Rules
- The
targetstring is the connection between controls and result containers. - Controls with different target IDs do not affect each other.
- Multiple target containers can share a target ID, but they share the same scoped request state.
- Empty target IDs are not useful at runtime; the PHP components show inline builder guidance when target is missing.
Facet Target Behavior
Facet Target owns the content that gets replaced. Its loop slot is the normal result state, and its fallback slot is shown when the refreshed loop produces no rendered items.
Important target props:
| Prop | Meaning |
|---|---|
target | Shared target ID. |
rerun_scripts | Allows scripts returned by refreshed markup to run again. Defaults to true. |
preview_fallback | Shows the fallback slot in Etch preview instead of the loop slot. |
scroll_to_top | Scrolls to the target after connected facet updates. |
used_with_map | Marks the target as map-paired, so map and result updates coordinate correctly. |
load_more_on_scroll | Adds internal offset and posts-per-page controls for infinite scroll. |
load_more_batch_size | Batch size used by infinite scroll. |
Nested loops have a specific rule: if a Facet Target lives inside another Etch loop, outer loop params must be resolved during the original render pass. The current implementation freezes those params through FacetLoopParamResolver before the target template is stored, and the E2E nested_loop_context scenario verifies that refreshed results keep the correct outer-loop context.
URL State
Facet state is serialized under the target ID. The E2E URL tests cover direct-link hydration for search, checkbox, radio, select, pagination, map state, ACF relationship, and mapped bundle filters.
Examples:
ome[products][category_name]=shoes
ome[products][meta_value:price]=50
ome[products][tax_query:facet_color]=red
ome[products][acf_relationship:facet_related_posts]=123
ome[products][geo_bbox]=40.5,-74.3,40.9,-73.7
The exact URL key depends on the facet clause type and mode-specific options such as meta_key, taxonomy, or date column.
Pagination, Load More, and Reset
Pagination Facetwrites pagination state for a target and receives total pages, total items, current page, per-page, and offset metadata from responses.Load More Facetwrites hidden offset and posts-per-page controls, then appends another batch through the same target request path.load_more_on_scrollonFacet Targetuses the same internal offset mechanism without requiring a visible button.Reset Facetclears all controls connected to the target and returns the target to its unfiltered state.
When any normal facet value changes, pagination resets to page 1. The multi-facet E2E scenario verifies that changing category_name after navigating to page 2 resets pagination before showing the narrowed result set.
Map Pairing
Map Facet is a facet control with type geo_bbox. It sends the map viewport as a bounding box and reads Map POI elements from the connected target loop.
Use a map-paired setup when:
- the target loop renders listings,
- each listing includes a
Map POI, - the map and result target share the same target ID,
- the target sets
used_with_mapwhen map coordination is needed.
The map runtime can use detailed POI markup for smaller sets and lightweight coordinate responses for large sets.