

Live search results in the default Modern Grid Cards layout.
OmniDirectory is one flexible directory engine for searchable WordPress directories: staff, members, professionals, businesses, organizations and more. Every entry has a name, a photo, relabelable directory fields, Phone, Email, Bio, Website, a Directory Category and a profile page, shown in your choice of search and profile layouts. You adapt it to your use case by relabeling fields — no code required.
Add a directory to any page with the [omnidirectory_search] shortcode or with four Gutenberg blocks: Directory Search, Directory Category List, Directory Listings and Member Card.
Use it as a staff, employee, team, member, professional, medical, business, school, church, nonprofit, multilingual or Arabic/RTL directory. These are uses of the same engine, not separate modes with industry-specific fields.
Add the [omnidirectory_search] shortcode, or the Directory Search block, to any page for live AJAX search as visitors type. Search matches the entry’s name and Directory Category (developers can extend it with filters). Only published entries that are not password-protected are listed. Results are cached briefly, refreshed as soon as an entry changes, capped to a configurable limit, and protected by basic rate limiting.
Four blocks in the “OmniDirectory” block category. They need WordPress 6.0 or later.
[omnidirectory_search], with the same search box and results.Live search (the shortcode and the Directory Search block), Directory Listings and Member Card show only published members that are not password-protected. Search filters added by other plugins use their own queries and are not covered. Each block’s settings are described under “Using the blocks” below.
Each Directory Listings block pages on its own: moving one list to page 2 keeps every other list on the page where it is. This also applies to lists inside synced patterns in your posts and pages, and to lists in template parts and block widgets. Page links are plain links (they work without JavaScript), and each combination of pages has its own URL, so it can be bookmarked. See the FAQ for bookmarks, synced patterns and page caching.
The [omnidirectory_search] shortcode keeps working as before, with the same output and attributes, so existing pages need no change. You can keep using it, use the blocks, or use both on the same site.
On a single page, the combination that has been tested is several Directory Search blocks together with an [omnidirectory_search] shortcode: each of them searches on its own. Other blocks on the same page as the shortcode have not been specifically tested.
Search normalizes common Arabic letter variants (forms of Alef, ta marbuta / ha, and similar), and every layout uses the correct dir="rtl" or dir="ltr". Directory entries and categories are registered as translatable for Polylang and WPML (wpml-config.xml included).
With Polylang, the Directory Category List, Directory Listings and Member Card blocks show the categories and members of the page’s language; Directory Search searches exactly as the shortcode does. The blocks have not been tested with WPML.
Person JSON-LD (name, URL, photo, phone, email, website, bio, job title). The omnidirectory_structured_data filter ($schema, $post_id) can unset telephone/email, or return an empty array for none.Export downloads every entry as CSV. A cell that a spreadsheet could read as a formula (starting with = + – @, a tab, carriage return or line feed, or their full-width forms = + - @, also after spaces) gets a leading apostrophe, which import removes again. Phone numbers such as +46 70 123 45 67 and plain numbers are left as they are. Spreadsheets may show the apostrophe, and a file edited and saved again in a spreadsheet may lose it. Import replaces the whole directory with the file’s content; it doesn’t edit entries in place.
uploads/omnidirectory-imports/ under a random name. It is deleted as soon as its rows are staged, or when the import fails or is cancelled (“Cancel Import”). An import still staging that has made no progress for 24 hours is ended, and its file deleted, the next time WP-Cron runs or an administrator opens the Import page or uploads a file. On a site with little traffic or without WP-Cron, this can be later. While the file exists, the web server must block that folder. PHP cannot do this on Nginx, and the plugin cannot stop Nginx from listing or serving the folder without a deny rule. The file’s name is kept out of error messages and logs. Tested: Apache 2.4 with AllowOverride All, which honours the plugin’s .htaccess; Nginx 1.24 with location ^~ /wp-content/uploads/omnidirectory-imports/ { deny all; return 404; }. Other servers were not tested.Polylang: each entry is imported in the language from its Language Code column, and entries sharing a Translation Group value (last export column) are linked again as translations — only when the whole group was imported, one entry per language; otherwise a warning is shown. A file with a Language Code that is not a language of the site is refused before anything changes. Files without a Translation Group column are never linked automatically, not even by name. Translation Group values change after each import (entries are new posts).
Without Polylang (including WPML): a file with any Language Code or Translation Group value is refused before anything changes; empty columns import as before. WPML is not supported for these two columns.