This post is for the person who owns the "Find a Doctor" directory on a hospital or clinic-chain website: usually an SEO lead, a product manager or a web developer who has been asked why Google is crawling thousands of filter URLs and ranking none of them. It assumes you already know what a canonical tag and a robots.txt rule are. What it adds is a way to decide, filter by filter, what each URL should be allowed to do.
A doctor directory is a classic faceted navigation problem. Specialty, city, language, gender, insurance, fee band and "available today" can each be combined with the others. Ten specialties, twelve cities, six languages, two genders and an availability toggle already produce thousands of possible pages, most of which show the same three doctors in a different order. Some of those pages match real searches ("female gynaecologist in Pune"). Most do not.
The answer is not "index everything" or "block everything". It is a rule set, written down before the developers build it, that sorts every filter combination into one of four outcomes: index, canonicalise, noindex, or keep out of the crawl.
What Google actually says about faceted URLs
Google's guidance on managing faceted navigation separates two goals. If filtered URLs do not need to appear in Search, prevent crawling with robots.txt rules on the filter parameters or keep the filter state after a URL fragment. If they do need to appear, keep them crawlable and follow the URL practices on the same page.
Several details in that document matter for a directory:
- Use the standard
&between parameters. Commas, semicolons and brackets are often not read as separators. - If filters sit in the path, keep a fixed order, so
/doctors/cardiology/pune/never also exists as/doctors/pune/cardiology/. - Return a 404 for a combination with no results, rather than a soft page that says "0 doctors found" with a 200 status.
rel="canonical"may reduce crawling of the non-canonical versions over time, but gradually. It is not a crawl-budget switch.
Google's page on consolidating duplicate URLs adds two warnings that apply here. Do not use robots.txt to choose a canonical, and do not use noindex to choose a canonical within one site. Each tool has one job, and the matrix below respects that.
The four outcomes, defined
Index. The URL has a self-referencing canonical, appears in the sitemap, is linked from crawlable navigation, and has its own title, heading and intro. It earns this only if it has a distinct search demand and distinct content.
Canonicalise. The URL stays crawlable and usable, but its canonical points at a parent or cleaner version. Use this for near-duplicates that users may legitimately reach, such as the same list with a different sort order.
Noindex. The URL is crawlable, so Google can see the tag, but it asks not to be indexed. Use it for pages that are useful to a visitor but should not compete in results. Note that a noindex URL still consumes crawl effort, because Google must fetch it to see the tag.
Keep out of the crawl. A robots.txt disallow on the parameter pattern, or filter state that never becomes a crawlable URL. Use it for combinations that have no search value and would multiply into the thousands. The trade-off is that Google cannot see a canonical or noindex on a blocked URL, so never block a URL and also rely on a tag on it.
The decision matrix
Here is a starting matrix for a multi-specialty hospital directory in India. Treat it as a hypothesis to test against your own Search Console data, as the next section explains.
| Filter combination | Example | Default outcome | Why |
|---|---|---|---|
| Specialty alone | Cardiology doctors | Index | Clear demand, stable list, anchor of the directory |
| City alone | Doctors in Pune | Index if the site has a real presence there; otherwise canonicalise to the directory root | Location pages need genuine local content |
| Specialty + city | Cardiologists in Pune | Index when 3 or more doctors practise there (hypothetical threshold); otherwise 404 or canonicalise to specialty | Highest-intent pattern for directories |
| Specialty + city + language | Hindi-speaking paediatricians in Pune | Index only where Search Console shows demand and the doctor count supports it; else canonicalise to specialty + city | Language is a real patient need in some cities, not all |
| Specialty + gender | Female gynaecologists | Index for specialties where the query is common (women's health); otherwise noindex | Demand is concentrated in a few specialties |
| Specialty + city + gender | Female gynaecologists in Pune | Test case. Index only with enough doctors and a distinct heading | Thin quickly; each doctor's profile does the real work |
| Any + availability ("available today") | Cardiologists available today | Keep out of the crawl, or noindex | The list changes hourly; no stable page to rank |
| Any + sort order | Sorted by experience | Canonicalise to the unsorted URL, or keep out of the crawl | Same doctors, different order |
| Any + insurance, fee band | Cashless insurance filter | Noindex or keep out of the crawl by default | Individual-level data changes often and rarely matches a search |
| Three or more filters stacked | Specialty + city + language + gender | Keep out of the crawl | Combinatorial explosion, few results each |
| Page 2+ of any indexable list | Cardiologists in Pune, page 2 | Self-canonical, crawlable links | Each page has its own canonical; do not point all pages at page 1 |
The last row follows Google's pagination guidance, which says not to make the first page of a sequence the canonical for every page in it.
Four rules that settle most edge cases
A page earns an index only with content that differs. If the specialty + city page and the specialty + city + language page show the same doctors, the second adds no value to Google. If it shows a different subset, with an introduction written for that audience and a heading that names the language, it can.
Never index a page whose content changes hourly. "Available today" is the clearest example. A slot-based filter helps the visitor choose, but a list that is true at 10:00 and false at 14:00 is a poor landing page. Apply the filter with JavaScript or a parameter that is blocked from crawling, and let the profile pages carry availability.
Empty means 404. Generate links only to combinations that have at least one doctor, and return a 404 status for any that do not. A "no doctors found" page returning 200 is a soft error that will accumulate in Search Console.
One canonical logic, written in code. Do not let the template decide the canonical URL by whatever the browser address shows. Compute it from a whitelist of indexable facets and render the same tag on every variant.




