<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MohammadreZa Dehghani</title>
    <description>The latest articles on DEV Community by MohammadreZa Dehghani (@vitrinetoo).</description>
    <link>https://dev.to/vitrinetoo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4053385%2Fb3d41714-88c8-4ac5-ba90-474b449d2b22.png</url>
      <title>DEV Community: MohammadreZa Dehghani</title>
      <link>https://dev.to/vitrinetoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vitrinetoo"/>
    <language>en</language>
    <item>
      <title>How to Build a Professional Local Business Directory with WordPress (A Complete Guide)</title>
      <dc:creator>MohammadreZa Dehghani</dc:creator>
      <pubDate>Wed, 29 Jul 2026 14:28:14 +0000</pubDate>
      <link>https://dev.to/vitrinetoo/how-to-build-a-professional-local-business-directory-with-wordpress-a-complete-guide-14e</link>
      <guid>https://dev.to/vitrinetoo/how-to-build-a-professional-local-business-directory-with-wordpress-a-complete-guide-14e</guid>
      <description>&lt;p&gt;The Origin of This Guide&lt;br&gt;
A few months ago, I started working on a local business directory project for Eslamshahr, Iran (a city near Tehran). The goal was simple: create a searchable, user-friendly platform where local businesses could list their services and customers could find them easily.&lt;/p&gt;

&lt;p&gt;But as the project progressed, I encountered challenges that I hadn't anticipated. This guide shares everything I learned, from choosing the right architecture to implementing custom features and solving real-world problems along the way.&lt;/p&gt;

&lt;p&gt;The Challenge: What a Directory Website Actually Needs&lt;br&gt;
Before choosing tools, I needed to understand what a directory website requires at its core. At the data layer, nearly every directory shares the same three structural components :&lt;/p&gt;

&lt;p&gt;A custom post type that acts as the listing container&lt;/p&gt;

&lt;p&gt;Taxonomies that classify the listings&lt;/p&gt;

&lt;p&gt;Custom fields that store the listing details themselves&lt;/p&gt;

&lt;p&gt;For example, a restaurant directory might use a "Restaurant" post type, taxonomies for cuisine and location, and custom fields for opening hours, phone number, and price range. A real estate directory follows the same pattern, just with different fields. The architecture stays the same .&lt;/p&gt;

&lt;p&gt;This realization shaped my approach. Instead of searching for a "perfect" directory plugin that would do everything, I decided to build the structure myself to maintain full control over the content model and front-end architecture.&lt;/p&gt;

&lt;p&gt;Architecture Decisions&lt;br&gt;
Choice 1: Custom Post Types Approach&lt;/p&gt;

&lt;p&gt;Instead of relying on a single monolithic plugin that might limit flexibility later, I built the directory structure with Custom Post Types and Advanced Custom Fields (ACF) . ACF has supported custom post type and taxonomy registration directly in its admin UI since version 6.1, making the setup manageable from a single interface.&lt;/p&gt;

&lt;p&gt;Why this approach?&lt;/p&gt;

&lt;p&gt;Full control over the content model and templates&lt;/p&gt;

&lt;p&gt;Portability - the directory data stays separate from the design layer&lt;/p&gt;

&lt;p&gt;Customizability for niche requirements like unusual filtering or listing logic&lt;/p&gt;

&lt;p&gt;Keep in mind: this path requires some developer skills. ACF does not include front-end submissions, payment processing, or geolocation features out of the box. The developer builds or integrates everything else manually .&lt;/p&gt;

&lt;p&gt;Choice 2: Taxonomies for SEO Structure&lt;/p&gt;

&lt;p&gt;Taxonomies are essential for creating a scalable SEO architecture. I used at least two taxonomies:&lt;/p&gt;

&lt;p&gt;Category (what the listing is) - example: "Restaurants, Gyms, Furniture Stores"&lt;/p&gt;

&lt;p&gt;Location (where the listing exists) - example: specific neighborhoods or cities&lt;/p&gt;

&lt;p&gt;The SEO Advantage: Every public taxonomy-term combination automatically generates an indexable archive page. A directory with fifty cities and twenty categories can theoretically create 1000 searchable landing pages before individual listings are even considered. This structural archive system is why directories scale search visibility faster than flat-content sites .&lt;/p&gt;

&lt;p&gt;Implementation: The Code&lt;br&gt;
Step 1: Registering the Custom Post Type&lt;/p&gt;

&lt;p&gt;To manage businesses, I created a "Business" custom post type. The code was added to the functions.php file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="n"&gt;php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;create_business_post_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_post_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'business'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'labels'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Businesses'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'singular_name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Business'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'public'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'has_archive'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'supports'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'thumbnail'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'custom-fields'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'taxonomies'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'post_tag'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'create_business_post_type'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Adding Custom Fields with ACF&lt;/p&gt;

&lt;p&gt;For storing specific business information like address, phone number, website, and business hours, I used Advanced Custom Fields. This plugin allows you to add custom field groups and assign them to the Business post type. ACF Pro starts at $49/year for one site, scaling to $249/year for unlimited sites .&lt;/p&gt;

&lt;p&gt;Step 3: Taxonomies for Better Filtering&lt;/p&gt;

&lt;p&gt;Custom taxonomies were created to classify businesses by industry and location. This allowed users to filter listings by category (e.g., "Restaurants") or by neighborhood.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;create_industry_taxonomy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_taxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'industry'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'business'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'labels'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Industries'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'add_new_item'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Add New Industry'&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'public'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'hierarchical'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'create_industry_taxonomy'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Displaying Listings&lt;/p&gt;

&lt;p&gt;For the front-end, I created a custom loop to display businesses on the main directory page and archive pages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt;
&lt;span class="nv"&gt;$args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'post_type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'business'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'posts_per_page'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'tax_query'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// Add tax query conditions for filtering&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WP_Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: User Submission Forms&lt;/p&gt;

&lt;p&gt;To allow business owners to submit their listings, I implemented a front-end submission form using custom templates and hooks.&lt;/p&gt;

&lt;p&gt;Critical Step: SEO Protection with Canonical URLs&lt;br&gt;
When you publish the same content in multiple places, search engines must decide which version is the "canonical" (authoritative) source. If you don't tell them, they guess based on factors like:&lt;/p&gt;

&lt;p&gt;Which version got indexed first&lt;/p&gt;

&lt;p&gt;Which has more inbound links&lt;/p&gt;

&lt;p&gt;Which has stronger domain authority &lt;/p&gt;

&lt;p&gt;The Problem: If you cross-post a version of this guide to platforms like Dev.to without setting a canonical URL, they could outrank your original because they have higher domain authority than many personal or small business sites .&lt;/p&gt;

&lt;p&gt;The Solution: Add a canonical URL tag to any cross-posted versions. This tells search engines: "This page exists in multiple places, but this specific URL is the original source. Credit it there" .&lt;/p&gt;

&lt;p&gt;For Dev.to, you set this in the post editor by clicking the menu button and filling in your canonical URL, or by adding it to the front matter at the top of your post:&lt;/p&gt;

&lt;p&gt;yaml&lt;br&gt;
title: Your Post Title&lt;br&gt;
published: true&lt;br&gt;
tags: webdev, wordpress, tutorial&lt;br&gt;
canonical_url: &lt;a href="https://your-website.com/your-article-url" rel="noopener noreferrer"&gt;https://your-website.com/your-article-url&lt;/a&gt;&lt;br&gt;
This is a critical step that many publishers miss. Cross-posting without canonical URLs means you're "in a fight you'll probably lose" against high-authority platforms . If you post to multiple platforms like Medium and Hashnode, each has a slightly different UI for setting the canonical URL, but the principle is the same: always set it to your original .&lt;/p&gt;

&lt;p&gt;Real-World Challenges and Solutions&lt;br&gt;
Challenge 1: Handling Large Data&lt;/p&gt;

&lt;p&gt;With hundreds of businesses, the directory needed to handle large amounts of data efficiently while keeping everything organized. Using WordPress's built-in query optimization and proper indexing with ACF helped maintain performance.&lt;/p&gt;

&lt;p&gt;Challenge 2: User-Friendly Filtering&lt;/p&gt;

&lt;p&gt;Users expected to filter businesses by category, location, and other attributes. Implementing custom search and filter functionality required some custom coding but was worth the effort for user experience.&lt;/p&gt;

&lt;p&gt;Challenge 3: Mobile Responsiveness&lt;/p&gt;

&lt;p&gt;Over 60% of our users accessed the directory from mobile devices. Ensuring the directory was fully responsive was essential for user adoption.&lt;/p&gt;

&lt;p&gt;Challenge 4: Business Data Consistency&lt;/p&gt;

&lt;p&gt;Ensuring business owners entered clean, consistent data was challenging. Adding validation rules and clear guidance on the submission form helped maintain quality.&lt;/p&gt;

&lt;p&gt;Results and Key Takeaways&lt;br&gt;
The directory launched successfully and now serves as a valuable resource for the local community. Here are the key lessons I learned:&lt;/p&gt;

&lt;p&gt;Choose the right architecture - Custom Post Types with ACF give you maximum flexibility and control. Dedicated directory plugins work for simpler cases, but if you need custom functionality, building from scratch pays off.&lt;/p&gt;

&lt;p&gt;Structural SEO is powerful - The archive pages created by taxonomies generate hundreds of SEO-optimized landing pages automatically. This is one of the most underrated advantages of directory sites.&lt;/p&gt;

&lt;p&gt;Canonical URLs are not optional - If you cross-post content, always set the canonical URL to your original version. This is especially important when using high-authority platforms like Dev.to .&lt;/p&gt;

&lt;p&gt;Plan for scale - Your directory will grow. Design the architecture with scalability in mind from day one.&lt;/p&gt;

&lt;p&gt;User experience is everything - If the directory isn't easy to use, users won't return. Invest in search, filtering, and a clean mobile experience.&lt;/p&gt;

&lt;p&gt;Next Steps for Your Directory Project&lt;br&gt;
Ready to build your own directory? Here are some practical next steps:&lt;/p&gt;

&lt;p&gt;Plan your content model - What information does each listing need to include?&lt;/p&gt;

&lt;p&gt;Choose your development approach - Will you use ACF (requires developer skills) or a dedicated directory plugin? &lt;/p&gt;

&lt;p&gt;Set up proper SEO from day one - including canonical URLs if you plan to cross-post content&lt;/p&gt;

&lt;p&gt;Build a user submission workflow - How will business owners add their listings?&lt;/p&gt;

&lt;p&gt;Test with real users and iterate&lt;/p&gt;

&lt;p&gt;If this guide helped you, I'd love to hear about your own directory project in the comments. What challenges have you faced, and what solutions have worked for you?&lt;/p&gt;

&lt;p&gt;→ Visit our live directory: &lt;a href="https://vitrinetoo.ir/" rel="noopener noreferrer"&gt;vitrinetoo.ir&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://vitrinetoo.ir/" rel="noopener noreferrer"&gt;vitrinetoo.ir&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webdev</category>
      <category>wordpress</category>
    </item>
  </channel>
</rss>
