Docs / Developers / Directory Widget JavaScript API — Custom Embed Configuration

Directory Widget JavaScript API — Custom Embed Configuration

Customize your embedded directory widget with JavaScript. Pre-filter listings, require all filters before showing results, pre-fill from URL parameters, and more. No build step, just one snippet.

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.

For AI assistants. This page contains the complete widget JavaScript API. Paste the URL into ChatGPT, Claude, or your AI tool of choice when generating a custom embed snippet. The page is self-contained and produces working code on first try.

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

OptionTypeDescription
preFilterobjectRestrict listings before any user filtering. Declarative rules with and / or logic.
customFilterFunctionfunctionRun your own filter logic on each render. Most powerful option.
initialFilterobjectPre-select filter values when the widget loads.
urlParamsbooleanRead filter values from the page URL. Default: true.
localestringForce a specific display language (e.g. "en", "es").

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

ModeBehavior
andAll rules must match. Default.
orAt least one rule must match.

Operators

OperatorValueBehavior
containsstringFor tag and category fields, value is one of the field's values. For text fields, exact match.
contains_anyarrayMatch if any of the values is present. More efficient than multiple or rules on the same field.
contains_allarrayMatch only if every value is present.
not_containsstringInverse of contains.
equalsstringExact match. Same as contains for text fields.
not_equalsstringInverse 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.

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

PropertyTypeDescription
itemsarrayThe listings already filtered by built-in filters.
activeFiltersobjectCurrent filter values keyed by filter ID.
searchFiltersarrayThe widget's configured filters (id, type, label, config).
fieldsarrayThe widget's field definitions.
settingsobjectThe widget's full settings.
geoSearchLocationobject or nullActive 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

ReturnEffect
Array of itemsReplace the result list. Default empty-state message is used.
{ items, emptyMessage }Replace the result list and customize the empty-state message.
Preview before publishing. Custom filter functions run in your visitors' browsers on every filter change. Test your snippet on a staging page first, with the browser console open.

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 }

Locale

Force a specific display language. Defaults to your widget's configured default. Useful for serving the same widget in different languages on different pages.

config: { locale: "es" }

You manage available languages and translated phrases on the Phrases page.

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:

  • customFilterFunction returns nothing. The function must return either an array or an object with items. Returning undefined reverts 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. Check context.activeFilters in 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_any expects an array value).

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.

Still have questions?

We're happy to help anytime.

Get in Touch

Build your directory today

Set up in minutes. Works on any website.