Smart Directory Pro lets visitors filter the result set by facilities (WiFi, Parking, Outdoor seating, Wheelchair access, etc.) via a multi-checkbox “Features” group in the filter sidebar. Selecting multiple values requires the listing to have ALL of them. Cards render a small icon row of the listing’s facilities. And admins can mark which facilities are relevant for each category, so picking “Restaurants” replaces the WiFi / Parking generic set with a Delivery / Takeaway / Vegan / Outdoor-seating set tailored to the vertical.
The Features facet at a glance
The data already exists: every listing has a _sdp_facilities postmeta with a list of facility strings (the user types or picks them on the listing edit screen’s Facilities tab). What this release adds is exposing that data on the search side, as both a filter and a per-card visual.
The sidebar UI
The Features section sits below the Quality toggles in the filter sidebar. It’s populated from the discovery-facets endpoint, which tallies facility frequencies across the current result set. The list shows up to 8 facilities by default, sorted by descending frequency. A “Show more (N)” button reveals the remaining ones; clicking again hides them.
Each row is a labelled checkbox with the facility name and the count of listings in the current result set that have it. Selecting a checkbox immediately reruns the search and updates both the result list and the count on every other row (so once you pick “Delivery (28)”, the other counts re-tally against the “everything with Delivery” subset).
Amenity icons on cards
Each card renders the first five facilities as small icon chips below the meta row. Hovering a chip shows the facility name as a tooltip. If a listing has more than five, the sixth slot becomes a “+N” chip showing the rest count, with the remaining facility names in the hover title.
Icons map by facility name: “wifi” maps to ph-wifi-high, “parking” maps to ph-car, “wheelchair” maps to ph-wheelchair, and so on through about thirty common names. Unknown facilities fall back to ph-check-circle. The mapping lives in facilityIcon() inside sdp-search.js and mirrors the equivalent PHP map in the single-listing renderer, so the same WiFi chip on the card matches the same WiFi icon on the listing page.
AND-across-selected logic
Picking “Delivery” and “Takeaway” together returns only the listings that have BOTH. We chose AND rather than OR because it’s how visitors naturally read multi-select facets: “I want a restaurant that does delivery AND has outdoor seating.” OR is reachable by running two separate searches.
The SQL is a single meta_query block with 'relation' => 'AND' and one clause per selected facility. Each clause is a LIKE match against the serialised PHP array. The matched substring is the facility name wrapped in quotes (e.g. '"Delivery"'), which matches the way PHP serialises a string inside an array. It’s a clever-not-fragile choice: faster than normalising facilities into a separate relation table at our scale, and it sidesteps a JOIN.
// Real shipped code from src/Frontend/Search.php
if ( ! empty( $params['facilities'] ) ) {
$facility_clauses = [ 'relation' => 'AND' ];
foreach ( $params['facilities'] as $facility ) {
$facility_clauses[] = [
'key' => '_sdp_facilities',
'value' => '"' . $facility . '"',
'compare' => 'LIKE',
];
}
if ( count( $facility_clauses ) > 1 ) {
$args['meta_query'][] = $facility_clauses;
}
}
Category-aware narrowing
This is the killer feature. Without it, a user filtering by “Restaurants” still sees facilities like “Hairdresser-only-chair” or “Wedding-venue-licensed” in the Features facet. With it, admins configure a relevant-facility allowlist per category and the facet narrows to just those values.
To configure, go to Listings → Categories → Edit category. New field: Relevant features. Type a comma-separated list (“Delivery, Takeaway, Dine-in, Outdoor seating, Vegan, Gluten-free, Reservations, Family friendly”). Save.
From then on, whenever a user filters by exactly that one category, the discovery-facets endpoint intersects the result-set facility tally with the allowlist before returning. The sidebar JS shows the narrowed list and sets a facilities_filtered: true flag the UI can use to label the section (we don’t surface that flag visually today, but it’s there for theme integration).
_sdp_category_facilities as a sanitised array of strings. Saved via the standard edit_term hook in src/Core/Taxonomies.php. Read by RestAPI::category_facility_allowlist() during facet computation.The narrowing only kicks in when the user has selected exactly one category. Multi-category selections fall back to the global set because intersecting allowlists from two unrelated categories rarely produces a useful narrowing.
FAQ
Do facility values normalise across listings?
No, they’re free-text. “WiFi”, “Wi-Fi”, and “Free WiFi” are three separate facilities in the facet. The MetaBoxes admin offers a preset chip list to reduce drift, but if your team types whatever they like, the facet reflects that. Periodic cleanup is on you. A normalisation pass is on the roadmap.
How many facilities can a listing have?
Unbounded. The card shows the first five plus a “+N more” chip. There’s no DB limit beyond MySQL’s max longtext.
Can I disable the category narrowing globally?
Don’t set the allowlist on any category and you get the default behaviour: every facility present in the result set shows in the facet. The narrowing is opt-in per category.
How fast is this on a 10,000-listing site?
The facet endpoint runs the WP_Query for the current filter set without pagination, fetches IDs only, then tallies facilities by iterating the postmeta for each ID. On the mk.directory test site (10,006 listings), the typical facet response takes 80-180ms. The LIKE-on-serialised-array filter does an indexed scan via the postmeta index.