FacetWP REST API
FacetWP has two API endpoints: the /facetwp/v1/fetch
and the /facetwp/v1/refresh
endpoint. The /facetwp/v1/fetch
endpoint lets you query raw FacetWP data, with which you can build custom applications. The /facetwp/v1/refresh
endpoint is used by FacetWP itself in the front-end, for filtering.
By default, the /facetwp/v1/fetch
endpoint is disabled, to protect your data. To use it, you need to enable it.
The /facetwp/v1/refresh
endpoint is always open. If you want to protect this endpoint (and with that, facet filtering) from being accessed by non-logged-in users, see the section below.
Enable the fetch API endpoint
By default, the /facetwp/v1/fetch
API endpoint is disabled. To enable it, use this hook in your (child) theme’s functions.php:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_api_can_access', function( $boolean ) { return current_user_can( 'manage_options' ); });
Fetch endpoint URL
/wp-json/facetwp/v1/fetch
The /facetwp/v1/fetch
endpoint expects a POST
request with 1 parameter: data
. This parameter should be a string (a stringified JSON object).
Example
Let’s retrieve cars
with make = audi
, and also grab choices for the vehicle_type
facet.
Here’s the request JSON, before getting stringified:
How to use custom JavaScript code?
JavaScript code can be placed in your (child) theme's main JavaScript file. Alternatively, you can add it manually between
<script>
tags in the<head>
section of your (child) theme's header.php file. You can also load it with a hook in your (child) theme's functions.php file, or in the Custom Hooks add-on. To load the code only on pages with facets, use thefacetwp_scripts
hook. To load it on all pages, usewp_head
orwp_footer
. Or you can use a code snippets plugin. More infovar request_data = { 'data': { 'facets': { 'make': ['audi'], 'vehicle_type': [] }, 'query_args': { 'post_type': 'cars', 'posts_per_page': 4, 'paged': 1 } } };
Here’s the request using JavaScript’s fetch()
method:
How to use custom JavaScript code?
JavaScript code can be placed in your (child) theme's main JavaScript file. Alternatively, you can add it manually between
<script>
tags in the<head>
section of your (child) theme's header.php file. You can also load it with a hook in your (child) theme's functions.php file, or in the Custom Hooks add-on. To load the code only on pages with facets, use thefacetwp_scripts
hook. To load it on all pages, usewp_head
orwp_footer
. Or you can use a code snippets plugin. More infovar response = fetch('https://yoursite.com/wp-json/facetwp/v1/fetch', { 'method': 'POST', 'headers': { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + btoa('username:password') // base64-encoded }, 'body': JSON.stringify(request_data) }) .then(response => response.json()) .then(result => console.log(result));
Response data
{ "results":[ 1, 2, 3, 4 ], "facets":{ "make":{ "name":"make", "label":"Make", "type":"checkboxes", "selected":[ "audi" ], "choices":[ { "value":"audi", "label":"Audi", "depth":0, "count":20 } ] }, "vehicle_type":{ "name":"vehicle_type", "label":"Vehicle Type", "type":"checkboxes", "selected":[ ], "choices":[ { "value":"car", "label":"Car", "depth":0, "count":17 }, { "value":"suv", "label":"SUV", "depth":0, "count":3 }, { "value":"minivan", "label":"Minivan", "depth":0, "count":0 }, { "value":"truck", "label":"Truck", "depth":0, "count":0 }, { "value":"van", "label":"Van", "depth":0, "count":0 } ] } }, "pager":{ "page":1, "per_page":4, "total_rows":20, "total_pages":5 } }
Restrict the REST API (and facet filtering) to authenticated users
By default, the /facetwp/v1/fetch
endpoint is closed, unless enabled. But the /facetwp/v1/refresh
endpoint is always open, because it is used by FacetWP itself in the front-end, for filtering.
If you have facet pages that are only available to logged-in users, you may want to prevent non-logged-in users from accessing the /facetwp/v1/refresh
endpoint entirely. To do this, you could use a plugin like WordPress Rest API Authentication by miniOrange. The paid version of this plugin lets you protect selected endpoints of third-party plugins (like FacetWP).
You could also protect the whole WordPress REST API. Note that is not advisable to disable the WordPress REST API, because doing so will break WordPress Admin functionality that depends on the API being active. But you can require authentication for all WordPress REST API requests, effectively protecting the entire API from anonymous external access.
To do so, you can add the following code to your (child) theme’s functions.php, as advised in the WordPress REST API handbook:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
// Source: // https://developer.wordpress.org/rest-api/frequently-asked-questions/ add_filter( 'rest_authentication_errors', function( $result ) { // If a previous authentication check was applied, // pass that result along without modification. if ( true === $result || is_wp_error( $result ) ) { return $result; } // No authentication has been performed yet. // Return an error if user is not logged in. if ( ! is_user_logged_in() ) { return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) ); } // Our custom authentication check should have no effect // on logged-in requests return $result; });
Note that with the above code in place, also FacetWP’s /facetwp/v1/refresh
endpoint will be blocked from non-logged-in users. You’ll notice that facet filtering will now no longer work, also not for logged-in users, because by default, the WordPress REST API doesn’t pass along authentication data. To fix this, you need to add a second piece of code, as explained in this tutorial on how to pass authentication data through REST API requests.
Fix refresh issues when using user authentication
By default, the WordPress REST API doesn’t pass along authentication data. So if your FacetWP template or custom code depends on the currently logged-in user (e.g. with is_user_logged_in()
), or if you restrict WordPress REST API access to logged-in users, you will run into issues with your code not working after an AJAX refresh is triggered (which happens when using facets). See this tutorial on how to pass authentication data through REST API requests.
Trigger the indexer programmatically
You may need to trigger the indexer programmatically if posts aren’t saved via the normal /wp-admin/.
The second code sample on the above-linked section shows how to force FacetWP to re-index a specific post.