What did the check find?
- 108 of 700 sites (15.4%) had no working home page. For 57 of them (8.1% of all 700), the web address no longer resolves at all.
- Of the 552 working pages on the business's own domain, 268 (48.6%) carry Organization or LocalBusiness structured data. 92 (16.7%) carry all three AI search signals I checked: business structured data, an llms.txt file, and no AI crawler blocked in robots.txt.
- 21 (3.8%) block at least one of five AI crawlers in robots.txt.
- 49 (8.9%) never reach https, 147 (26.6%) have no meta description, and the median time to first byte came to 617 ms.
The statewide figures come from a random draw of 700 of the 2,102 business domains that OpenStreetMap lists for Alabama. The city figures cover every listed domain inside each city limit. Percentages for page checks use the 552 pages that stayed on the business's own domain as the base.
How do the five cities compare?
Each bar shows one city's share, with the statewide sample in grey for reference. The n under each name is the base for that bar. Montgomery and Tuscaloosa have small bases, so a single site moves their figures by two to three points. The Tuscaloosa study sets the Tuscaloosa figures beside the statewide sample on every measure.
Which kinds of business are most ready for AI search?
Dentists, doctors, clinics and vets had the fewest broken home pages and the most business structured data. Of them, 8.2% had no working home page, against 18.4% of shops, and 64.6% carried Organization or LocalBusiness JSON-LD, against 43.2% to 47.4% for the other kinds large enough to report. On all three AI search signals together the kinds sat close, between 14.5% and 20.3%, and with bases of 65 to 218 pages that gap is too small to rank them.
The chart leaves out trades and crafts, hotels and gyms, whose bases fall under 30 pages. In the tables, any figure with a base under 30 shows its count only.
| Kind of business | Base n (domains checked) | Base n (own-domain pages) | No working home page | Organization or LocalBusiness JSON-LD | All three AI signals | Blocks at least one AI crawler | No meta description |
|---|---|---|---|---|---|---|---|
| Restaurants, cafes and bars | 185 | 152 | 26 (14.1%) | 72 (47.4%) | 22 (14.5%) | 3 (2.0%) | 44 (28.9%) |
| Health and vets | 73 | 65 | 6 (8.2%) | 42 (64.6%) | 11 (16.9%) | 2 (3.1%) | 13 (20.0%) |
| Shops | 294 | 218 | 54 (18.4%) | 103 (47.2%) | 38 (17.4%) | 7 (3.2%) | 58 (26.6%) |
| Trades and crafts | 36 | 27 | 5 (13.9%) | 14 of 27, base too small | 5 of 27, base too small | 1 of 27, base too small | 5 of 27, base too small |
| Offices and professional services | 93 | 74 | 14 (15.1%) | 32 (43.2%) | 15 (20.3%) | 6 (8.1%) | 23 (31.1%) |
| Hotels | 4 | 3 | 1 of 4, base too small | 1 of 3, base too small | 0 of 3, base too small | 0 of 3, base too small | 1 of 3, base too small |
| Gyms | 15 | 13 | 2 of 15, base too small | 4 of 13, base too small | 1 of 13, base too small | 2 of 13, base too small | 3 of 13, base too small |
| All kinds | 700 | 552 | 108 (15.4%) | 268 (48.6%) | 92 (16.7%) | 21 (3.8%) | 147 (26.6%) |
The second table pools every domain checked, the statewide draw plus the five city lists. Cities carry more weight in it than in the state as a whole, so it gives each kind a larger count but no statewide estimate. It also gives trades and crafts a base large enough for percentages.
| Kind of business | Base n (domains checked) | Base n (own-domain pages) | No working home page | Organization or LocalBusiness JSON-LD | All three AI signals | Blocks at least one AI crawler | No meta description |
|---|---|---|---|---|---|---|---|
| Restaurants, cafes and bars | 351 | 294 | 43 (12.3%) | 136 (46.3%) | 38 (12.9%) | 9 (3.1%) | 93 (31.6%) |
| Health and vets | 106 | 94 | 8 (7.5%) | 60 (63.8%) | 15 (16.0%) | 3 (3.2%) | 17 (18.1%) |
| Shops | 462 | 354 | 78 (16.9%) | 168 (47.5%) | 63 (17.8%) | 19 (5.4%) | 89 (25.1%) |
| Trades and crafts | 56 | 42 | 8 (14.3%) | 23 (54.8%) | 8 (19.0%) | 1 (2.4%) | 8 (19.0%) |
| Offices and professional services | 171 | 139 | 22 (12.9%) | 72 (51.8%) | 22 (15.8%) | 8 (5.8%) | 38 (27.3%) |
| Hotels | 7 | 5 | 2 of 7, base too small | 3 of 5, base too small | 1 of 5, base too small | 0 of 5, base too small | 1 of 5, base too small |
| Gyms | 23 | 21 | 2 of 23, base too small | 8 of 21, base too small | 4 of 21, base too small | 3 of 21, base too small | 4 of 21, base too small |
| All kinds | 1,176 | 949 | 163 (13.9%) | 470 (49.5%) | 151 (15.9%) | 43 (4.5%) | 250 (26.3%) |
Each domain takes the kind of business that its OpenStreetMap listings carry most often. Restaurants, cafes and bars covers amenity=restaurant, cafe, bar and fast_food. Health and vets covers amenity=dentist, doctors, clinic and veterinary. Shops covers every shop tag, trades and crafts every craft tag, and offices and professional services every office tag. Hotels covers tourism=hotel and gyms covers leisure=fitness_centre.
Full results by check
Each table lists the count, the share and the base n for the statewide sample and the five cities. Download every figure as a CSV file. It holds counts, bases and percentages only.
Does the home page work?
| Area | Base n (domains checked) | Working home page (status 200) | No working home page | Web address no longer resolves | Working page ends on a different domain |
|---|---|---|---|---|---|
| Alabama (random sample) | 700 | 592 (84.6%) | 108 (15.4%) | 57 (8.1%) | 40 of 592 (6.8%) |
| Tuscaloosa | 60 | 51 (85.0%) | 9 (15.0%) | 2 (3.3%) | 4 of 51 (7.8%) |
| Birmingham | 218 | 199 (91.3%) | 19 (8.7%) | 8 (3.7%) | 12 of 199 (6.0%) |
| Huntsville | 279 | 251 (90.0%) | 28 (10.0%) | 8 (2.9%) | 11 of 251 (4.4%) |
| Montgomery | 44 | 33 (75.0%) | 11 (25.0%) | 3 (6.8%) | 2 of 33 (6.1%) |
| Mobile | 86 | 73 (84.9%) | 13 (15.1%) | 9 (10.5%) | 8 of 73 (11.0%) |
Statewide, the 108 failures break down as 57 addresses that did not resolve, 19 404 errors, 9 403 errors, 6 certificates that failed verification, 5 timeouts and 12 other errors. A page that ends on a different domain counts as working but leaves the base for the checks below.
Basics on the business's own page
| Area | Base n (own-domain pages) | Ends on https | Plain http only, never https | Viewport tag for phones |
|---|---|---|---|---|
| Alabama (random sample) | 552 | 503 (91.1%) | 49 (8.9%) | 521 (94.4%) |
| Tuscaloosa | 47 | 44 (93.6%) | 3 (6.4%) | 44 (93.6%) |
| Birmingham | 187 | 169 (90.4%) | 18 (9.6%) | 176 (94.1%) |
| Huntsville | 240 | 220 (91.7%) | 20 (8.3%) | 226 (94.2%) |
| Montgomery | 31 | 31 (100.0%) | 0 (0.0%) | 30 (96.8%) |
| Mobile | 65 | 62 (95.4%) | 3 (4.6%) | 61 (93.8%) |
| Area | Base n (own-domain pages) | Page title | Meta description | No meta description | All four: https, viewport, title, meta description |
|---|---|---|---|---|---|
| Alabama (random sample) | 552 | 526 (95.3%) | 405 (73.4%) | 147 (26.6%) | 379 (68.7%) |
| Tuscaloosa | 47 | 44 (93.6%) | 34 (72.3%) | 13 (27.7%) | 31 (66.0%) |
| Birmingham | 187 | 176 (94.1%) | 131 (70.1%) | 56 (29.9%) | 123 (65.8%) |
| Huntsville | 240 | 231 (96.3%) | 165 (68.8%) | 75 (31.3%) | 154 (64.2%) |
| Montgomery | 31 | 30 (96.8%) | 26 (83.9%) | 5 (16.1%) | 26 (83.9%) |
| Mobile | 65 | 65 (100.0%) | 58 (89.2%) | 7 (10.8%) | 54 (83.1%) |
Structured data
| Area | Base n (own-domain pages) | Any JSON-LD | Organization or LocalBusiness JSON-LD |
|---|---|---|---|
| Alabama (random sample) | 552 | 340 (61.6%) | 268 (48.6%) |
| Tuscaloosa | 47 | 28 (59.6%) | 21 (44.7%) |
| Birmingham | 187 | 128 (68.4%) | 95 (50.8%) |
| Huntsville | 240 | 146 (60.8%) | 110 (45.8%) |
| Montgomery | 31 | 19 (61.3%) | 13 (41.9%) |
| Mobile | 65 | 48 (73.8%) | 40 (61.5%) |
AI crawlers and llms.txt
| Area | Base n (own-domain pages) | robots.txt present | Blocks at least one of the five AI crawlers | Blocks all five | llms.txt file | All three: business JSON-LD, llms.txt, no AI crawler blocked |
|---|---|---|---|---|---|---|
| Alabama (random sample) | 552 | 510 (92.4%) | 21 (3.8%) | 4 (0.7%) | 139 (25.2%) | 92 (16.7%) |
| Tuscaloosa | 47 | 45 (95.7%) | 7 (14.9%) | 1 (2.1%) | 9 (19.1%) | 6 (12.8%) |
| Birmingham | 187 | 174 (93.0%) | 10 (5.3%) | 2 (1.1%) | 47 (25.1%) | 33 (17.6%) |
| Huntsville | 240 | 215 (89.6%) | 10 (4.2%) | 0 (0.0%) | 52 (21.7%) | 35 (14.6%) |
| Montgomery | 31 | 29 (93.5%) | 0 (0.0%) | 0 (0.0%) | 6 (19.4%) | 3 (9.7%) |
| Mobile | 65 | 63 (96.9%) | 3 (4.6%) | 0 (0.0%) | 17 (26.2%) | 12 (18.5%) |
| Area | Base n (own-domain pages) | Blocks GPTBot | Blocks ClaudeBot | Blocks PerplexityBot | Blocks Google-Extended | Blocks CCBot |
|---|---|---|---|---|---|---|
| Alabama (random sample) | 552 | 17 (3.1%) | 17 (3.1%) | 6 (1.1%) | 17 (3.1%) | 20 (3.6%) |
| Tuscaloosa | 47 | 6 (12.8%) | 7 (14.9%) | 2 (4.3%) | 4 (8.5%) | 6 (12.8%) |
| Birmingham | 187 | 8 (4.3%) | 8 (4.3%) | 2 (1.1%) | 7 (3.7%) | 9 (4.8%) |
| Huntsville | 240 | 9 (3.8%) | 7 (2.9%) | 1 (0.4%) | 6 (2.5%) | 6 (2.5%) |
| Montgomery | 31 | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) |
| Mobile | 65 | 2 (3.1%) | 2 (3.1%) | 0 (0.0%) | 2 (3.1%) | 3 (4.6%) |
Speed
| Area | Base n (own-domain pages) | Median first byte | 75th percentile first byte | First byte over 800 ms | Median HTML download | HTML download over 2 seconds | Median HTML size |
|---|---|---|---|---|---|---|---|
| Alabama (random sample) | 552 | 617 ms | 828 ms | 147 (26.6%) | 738 ms | 45 (8.2%) | 140 KB |
| Tuscaloosa | 47 | 614 ms | 972 ms | 16 (34.0%) | 734 ms | 4 (8.5%) | 141 KB |
| Birmingham | 187 | 561 ms | 726 ms | 38 (20.3%) | 670 ms | 8 (4.3%) | 154 KB |
| Huntsville | 240 | 622 ms | 875 ms | 75 (31.3%) | 760 ms | 20 (8.3%) | 133 KB |
| Montgomery | 31 | 534 ms | 710 ms | 4 (12.9%) | 735 ms | 2 (6.5%) | 135 KB |
| Mobile | 65 | 619 ms | 989 ms | 24 (36.9%) | 796 ms | 7 (10.8%) | 138 KB |
The OpenStreetMap listing
| Area | Base n (domains checked) | Listing has opening hours | Listing has a phone number |
|---|---|---|---|
| Alabama (random sample) | 700 | 400 (57.1%) | 568 (81.1%) |
| Tuscaloosa | 60 | 36 (60.0%) | 44 (73.3%) |
| Birmingham | 218 | 114 (52.3%) | 134 (61.5%) |
| Huntsville | 279 | 183 (65.6%) | 242 (86.7%) |
| Montgomery | 44 | 27 (61.4%) | 38 (86.4%) |
| Mobile | 86 | 46 (53.5%) | 72 (83.7%) |
Social pages in place of a website
| Area | Base n (listed web addresses) | Social page |
|---|---|---|
| All of Alabama | 2,191 | 89 (4.1%) |
| Tuscaloosa | 63 | 3 (4.8%) |
| Birmingham | 220 | 2 (0.9%) |
| Huntsville | 322 | 43 (13.4%) |
| Montgomery | 45 | 1 (2.2%) |
| Mobile | 86 | 0 (0.0%) |
This row counts every listing in Alabama, before the random draw.
Method
Sample frame
Business listings came from OpenStreetMap through the public Overpass API at overpass-api.de on 9 November 2026. The statewide query ran at 22:05 UTC and the five city queries between 22:19 and 22:31 UTC. The query asks for every Alabama listing tagged shop, craft or office, every restaurant, cafe, bar, fast food outlet, dentist, doctor's office, clinic and veterinarian, every hotel and every fitness centre, where the listing has a website or contact:website tag.
[out:json][timeout:180];
area["ISO3166-2"="US-AL"]["admin_level"="4"]->.a;
(
nwr["shop"]["website"](area.a);
nwr["shop"]["contact:website"](area.a);
nwr["craft"]["website"](area.a);
nwr["craft"]["contact:website"](area.a);
nwr["office"]["website"](area.a);
nwr["office"]["contact:website"](area.a);
nwr["amenity"~"^(restaurant|cafe|bar|dentist|doctors|clinic|veterinary|fast_food)$"]["website"](area.a);
nwr["amenity"~"^(restaurant|cafe|bar|dentist|doctors|clinic|veterinary|fast_food)$"]["contact:website"](area.a);
nwr["tourism"="hotel"]["website"](area.a);
nwr["tourism"="hotel"]["contact:website"](area.a);
nwr["leisure"="fitness_centre"]["website"](area.a);
nwr["leisure"="fitness_centre"]["contact:website"](area.a);
);
out tags center;Each city query swaps the second line for the line below, with the Wikidata id of the city: Q79580 for Tuscaloosa, Q79867 for Birmingham, Q79860 for Huntsville, Q29364 for Montgomery and Q79875 for Mobile.
area["wikidata"="QID"]["boundary"="administrative"]["admin_level"="8"]->.a;Chains, government and social pages
I dropped national and regional chains. A listing counts as a chain when it carries a brand or brand:wikidata tag, and any website shared with a brand-tagged listing went too. That step removed 5,049 listings and 575 chain domains. I also dropped 154 government, school, religious, nonprofit and association listings, including any .gov, .edu, .mil or .al.us address, and 1 listing with an unusable address. 89 Facebook, Instagram and Linktree addresses went into the social page count. That left 2,102 unique business domains: Tuscaloosa 60, Birmingham 218, Huntsville 279, Montgomery 44, Mobile 86, and 1,415 elsewhere in Alabama.
The draw
The statewide sample is a simple random draw of 700 of the 2,102 domains, using Python's random module with seed 20261109. The city figures cover every domain in each city, so they count the whole OpenStreetMap list for that city.
The checks
One script ran once on 9 November 2026, from 22:32 to 22:41 UTC, on one computer in Tuscaloosa. It read the home page only, ran at most four sites at a time, allowed 10 seconds per request and sent an ordinary Chrome user agent. It requested http://domain/ and followed redirects. If that address refused the connection, it tried https://domain/ once. It made no other retries.
- Working home page. The final response has status 200.
- Own domain. The final address stays on the listed domain. Pages that end on another domain leave the base for every check below.
- https. The final address uses https.
- Viewport, title, meta description. The page has a viewport meta tag, a title with text in it and a meta description with text in it.
- Business structured data. The page has JSON-LD with a type that schema.org lists under Organization, which takes in LocalBusiness and its subtypes such as Restaurant and Dentist.
- AI crawler blocked. The script read robots.txt under RFC 9309. A crawler counts as blocked when the group that applies to it, its own named group or else the group for all crawlers, disallows the home page. The five crawlers are GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot (Perplexity), Google-Extended (Google AI training control) and CCBot (Common Crawl).
- llms.txt. The file returns status 200 as plain text with a markdown heading or quote line. An HTML page or a copy of robots.txt does not count. The script fetched every hit a second time to apply this test.
- All three AI signals. Business structured data, an llms.txt file and none of the five crawlers blocked.
- Time to first byte and HTML download. Wall-clock time from the request to the first byte and to the end of the HTML, including redirects and connection setup.
- Opening hours and phone. These come from the OpenStreetMap tags, not from the website.
Limits
- These timings say nothing about PageSpeed or Core Web Vitals. They cover one machine waiting for the HTML of the home page, with no images, scripts or rendering.
- Each site got one try. A site that was down for a few minutes counts as not working, and some sites that block automated requests may show up as not working too.
- OpenStreetMap depends on volunteers. A business appears only if someone mapped it with a website, coverage differs from city to city, and some listings are out of date.
- Montgomery (44 domains) and Tuscaloosa (60 domains) are small groups, so one site moves their percentages by two to three points.
- robots.txt states a request to crawlers. It does not show firewall or hosting rules that turn AI crawlers away, which some hosts apply by default.
- Many sites get structured data, robots rules and llms.txt from their website platform or an SEO plugin. The figures describe what visitors and crawlers receive, whoever made the choice.
- Python's certificate store judged the certificates, and it can reject a few sites that a browser would load.
- The structured data check read JSON-LD only, so it missed microdata and RDFa.
- A few regional businesses with several locations and no brand tag remain in the data.
What owners can fix
- Run the free AI visibility check on your own site. It reads your robots.txt, llms.txt and home page and lists what to fix.
- If your web address no longer works, claim your Google listing first, so customers can still find your phone number and hours.
- Add a plain sentence that names the business, what it does and the town it serves. The post on how to write a page an AI will quote shows the sentence shape.
- For structured data, llms.txt and crawler rules in one place, read AI websites for small businesses.
Common questions
What did the Alabama small business website study measure?
It checked the home page of each business website for a working response, https, a viewport tag, a title, a meta description and Organization or LocalBusiness JSON-LD. It also read robots.txt for five AI crawlers, looked for an llms.txt file and timed the first byte and the HTML download from one computer in Tuscaloosa.
How was the sample drawn?
Business listings with a website came from OpenStreetMap through the Overpass API on 9 November 2026. After removing chains, government and nonprofit offices and social media pages, 2,102 business domains remained in Alabama. The statewide figures come from a simple random draw of 700 of them. The Tuscaloosa, Birmingham, Huntsville, Montgomery and Mobile figures cover every domain inside each city limit.
Can I check my own website the same way?
Yes. The free AI visibility check at purcellventures.co/ai-visibility-check reads your robots.txt, llms.txt and home page, including the title, meta description, structured data and https, and lists what to fix.
Can I use the data?
Yes. The aggregate figures and the CSV carry a Creative Commons Attribution 4.0 license. Credit Purcell Ventures and OpenStreetMap contributors, whose listings under the Open Database License formed the sample frame. The file holds counts and percentages only, with no domains or business names.
Data credit and license
Listing data © OpenStreetMap contributors, available under the Open Database License. The aggregate figures on this page and in the CSV carry a Creative Commons Attribution 4.0 license. Credit Purcell Ventures and OpenStreetMap contributors when you use them.