You set up a directory widget. You want it to behave a specific way on a specific page: maybe show only one category of listings, require visitors to pick all filters before seeing results, or pre-fill filters from a URL.
This page is the complete reference for the widget's JavaScript configuration. Each option is opt-in, well-defined, and works with the same embed snippet you already have.
You don't need code to use EmbedDirectory
Most customers never touch this page. The dashboard handles everything: layout, filters, branding, custom fields, integrations. If your goal is to add a directory to your site, see the quick start guide.
The JavaScript API is for customers who want custom behavior the dashboard doesn't expose. If something here looks tricky, email hello@embeddirectory.com and we'll write the snippet for you.
Quick Start
The basic embed snippet is two pieces: a container element and a script that initializes the widget into it.
<div id="embed-directory-widget"></div>
<script>
(function() {
var script = document.createElement("script");
script.src = "https://embed.embeddirectory.com/widget.js";
script.async = true;
script.onload = function() {
window.EmbedDirectoryWidget.init({
elementId: "embed-directory-widget",
widgetId: "widget_xxxxxxxxxxxxxxxx"
});
};
document.head.appendChild(script);
})();
</script>
Replace widget_xxxxxxxxxxxxxxxx with the widget ID from your Embed page. That's a complete, working embed.
To customize behavior, add a config object alongside elementId and widgetId. Every option below goes inside config.
Configuration Reference
| Option | Type | Description |
|---|---|---|
preFilter | object | Restrict listings before any user filtering. Declarative rules with and / or logic. |
dropdownWildcards | object | Tag values that match every dropdown selection, like a "Statewide" tag in a city filter. |
customFilterFunction | function | Run your own filter logic on each render. Most powerful option. |
initialFilter | object | Pre-select filter values when the widget loads. |
urlParams | boolean | Read filter values from the page URL. Default: true. |
locale | string | Lock the display language (e.g. "en", "es"). Left out, the widget follows the page and the visitor's browser. |
A Note on Field and Filter Labels
Examples below reference fields and filters by their dashboard label (e.g. "Make", "Year"). This reads naturally and matches what you see in your dashboard.
Labels are matched case-insensitively. If multiple fields share a label, the widget uses the first match and logs a console warning. If you rename a field later, update your snippet.
For rename-safe references, use the field's numeric ID instead. The field_id is shown in your widget settings or in the REST API field list. Both forms work everywhere a field or filter is referenced.
Pre-Filter Rules
Restrict the underlying listing set before any visitor interaction. Useful when you want one widget to show a specific slice of your directory: only one category, only listings in a region, or anything you can express as a rule.
config: {
preFilter: {
mode: "and",
rules: [
{ field: "Category", operator: "contains", value: "Hotel" }
]
}
}
Modes
| Mode | Behavior |
|---|---|
and | All rules must match. Default. |
or | At least one rule must match. |
Operators
| Operator | Value | Behavior |
|---|---|---|
contains | string | For tag and category fields, value is one of the field's values. For text fields, exact match. |
contains_any | array | Match if any of the values is present. More efficient than multiple or rules on the same field. |
contains_all | array | Match only if every value is present. |
not_contains | string | Inverse of contains. |
equals | string | Exact match. Same as contains for text fields. |
not_equals | string | Inverse of equals. |
Combine Rules
preFilter: {
mode: "and",
rules: [
{ field: "Category", operator: "contains", value: "Restaurant" },
{ field: "City", operator: "contains_any", value: ["Austin", "Denver"] }
]
}
This shows restaurants located in Austin or Denver. The outer mode is and (both rules must match); contains_any handles the Austin-or-Denver part inside the second rule.
Dropdown Wildcard Values
Some listings serve every area, not just one. Think of a provider directory filtered by city, where a handful of providers work statewide. A visitor who picks their city should still see them.
dropdownWildcards marks specific tag values as always-matching for a dropdown. Whatever the visitor selects, listings tagged with a wildcard value stay in the results.
config: {
dropdownWildcards: {
"Service Area": ["Statewide", "Nationwide"]
}
}
With this config, selecting "Austin" in the Service Area dropdown shows listings tagged Austin plus every listing tagged Statewide or Nationwide. While nothing is selected, the dropdown behaves as usual and shows everything.
Keys reference the dropdown's field by label or numeric ID, the same way preFilter rules do. Values are the tag values to treat as wildcards, matched case-insensitively. Wildcards on one field leave your other dropdowns untouched.
Custom Filter Function
A function you define that runs after the built-in filter pipeline on every render. Use this when declarative preFilter rules aren't enough: dynamic logic, conditional empty states, or filtering tied to your own data.
The function receives a context object and returns either an array of items or an object with items and an optional emptyMessage.
Context Object
| Property | Type | Description |
|---|---|---|
items | array | The listings already filtered by built-in filters. |
activeFilters | object | Current filter values keyed by filter ID. |
searchFilters | array | The widget's configured filters (id, type, label, config). |
fields | array | The widget's field definitions. |
settings | object | The widget's full settings. |
geoSearchLocation | object or null | Active location-search coordinates, if any. |
Example: Require All Filters Before Showing Results
A common pattern: hold back results until the visitor has selected every filter, then show the matching listing.
config: {
customFilterFunction: function(context) {
var hasValue = function(value) {
if (value === null || value === undefined) return false;
if (typeof value === "string") return value.trim().length > 0;
if (Array.isArray(value)) return value.length > 0;
if (typeof value === "object") return Object.keys(value).length > 0;
return true;
};
var allFiltersSet = context.searchFilters.every(function(filter) {
return hasValue(context.activeFilters[filter.id]);
});
if (!allFiltersSet) {
return {
items: [],
emptyMessage: "Please select all " + context.searchFilters.length + " filters to see your match."
};
}
return context.items.slice(0, 1);
}
}
This pattern reads the widget's actual filter list at runtime, so it keeps working if you add, remove, or rename filters in the dashboard.
Return Values
| Return | Effect |
|---|---|
| Array of items | Replace the result list. Default empty-state message is used. |
{ items, emptyMessage } | Replace the result list and customize the empty-state message. |
Initial Filter Values
Pre-select filter values when the widget loads. Useful for landing pages dedicated to a specific category, location, or audience.
config: {
initialFilter: {
"Category": "Restaurant",
"City": "Austin"
}
}
URL parameters take priority over initialFilter values. If a visitor lands on a URL with filter parameters, those win.
URL Parameters
The widget reads filter values from the page URL automatically. This is on by default. Set urlParams: false to opt out.
?q=coffee
?filter_City=Austin
?filter_Make=Honda
| Parameter | Effect |
|---|---|
q or search |
Fills the first search filter. |
filter_<Label> |
Fills the filter whose linked field matches <Label>. |
<type> (e.g. dropdown) |
If only one filter of that type exists, fills it. |
For range filters, use _min and _max suffixes:
?filter_Price_min=10&filter_Price_max=100
To disable URL parameter handling entirely:
config: { urlParams: false }
Language
Leave locale out and the widget works out the language on its own, checking in this order: ?ed_lang= or a /fr/ path segment in the URL, then the page's <html lang>, then the visitor's browser languages, then your default language. That covers translated sites built with Wix Multilingual, WPML and similar.
Set locale when a page should always render in one language, whoever is visiting:
config: { locale: "es" }
Regional codes fall back to their base language, so fr-CA reads the fr phrases. Arabic and Hebrew get dir="rtl" on the widget.
If your site has its own language toggle, drive the widget from it:
window.EmbedDirectoryWidget.setLanguage('fr');
Interface wording, field labels, tags and listing text all switch together, with no reload and no refetch. window.EmbedDirectoryWidget.getLanguage() returns the active code.
Languages, phrases and label translations live on the Translations page. Listing text carries its own translations: see Multiple Languages.
Debugging
Open your browser's developer console while the widget loads. The widget logs each step of its filter pipeline (Applying pre-filter, Applying custom filter function, After ... filter:) so you can see how listings move through your configuration.
If you reference a field or filter by label that doesn't match (typo, rename, ambiguous name), the widget logs a single warning per unique reference:
[EmbedDirectory] Field "Make" not found. If you renamed it, update
your snippet, or use the field's numeric ID.
Common gotchas:
-
customFilterFunctionreturns nothing. The function must return either an array or an object withitems. Returningundefinedreverts to the built-in filtered list. -
Filter values look "set" but aren't. Range filters use
[min, max]arrays; toggle filters use booleans; multi-select filters use arrays. Checkcontext.activeFiltersin the console to see actual shapes. -
Pre-filter rule has no effect. The console warning will tell you if the field reference didn't resolve. If there's no warning, double-check the operator matches your data type (e.g.
contains_anyexpects an arrayvalue).
Need Help?
If you're not sure how to express what you want, send the goal in plain language to hello@embeddirectory.com. We'll write the snippet for you.
For programmatic listing management (creating, updating, syncing listings from your own systems), see the REST API documentation.