I ran an "agentic commerce" readiness score against three lodging sites I work on. They scored between 37 and 51 percent. That looked bad until I read where the points went: 27 of the 70 points asked for things a motel should not have. A product schema with a barcode number. An Open Graph type of "product". A payment SDK on the page. A checkout protocol file. OAuth metadata for an API that does not exist. A perfectly built motel site tops out somewhere near 61 to 64 percent on that score, below its own "ready" line.
Worse, the tool's fix prompt would have told an AI coding agent to add Product markup to hotel rooms. The score was mine, by the way. I built it for product pages, and it does that job. It just answers a store's question, and a motel is not a store.
So I wrote down what an AI assistant actually needs when it helps a guest book a room, checked the same three sites against that list, fixed what was missing, and turned the list into checks. This post is the general version. It applies to any hotel, motel, inn, campground or other business that takes bookings by date.
Check your own site. The Mega Analyzer now runs six "Agent booking readiness" rows inside its Hotel / lodging readiness card, and the Agent Endpoint Inspector checks the agent-file side. Both run only on lodging and booking sites, so a store, a restaurant or a plumber sees nothing new. Free, no signup.
What a store check asks for, and why it misleads on lodging
Retail agent readiness is built around one transaction: an agent picks a product and buys it. So the checks look for the things that transaction needs. A Product node with a GTIN so the agent knows exactly which item it is. A visible "Add to cart" or "Buy now". A payment provider the agent can hand off to. Discovery files for the checkout protocols. Authorization metadata for the API the agent will call.
A motel room is not an item with a barcode, and the guest should not be "bought" a room by an agent at all. Here is how the retail score went wrong on lodging, beyond the points it could never award:
- The organization check missed the business. A page whose top-level JSON-LD type was
Motelfailed the "Organization or LocalBusiness" check, even though Motel is a LocalBusiness subtype. A page that referred to the business only by@idfailed too. - The call-to-action check read the wrong words. A sentence about returning keys at checkout passed as a buy button, because it contains the word "checkout". "Book a room" and "Reserve" did not count.
- A correct answer scored as a failure. A 404 at
/.well-known/oauth-protected-resourceis how a public, read-only site says "no authorization needed". The retail score counted it against the site.
None of that is a bug in the store checks. It is what happens when you grade one kind of business with another kind's rubric. The useful question for lodging is different.
What the assistant is actually doing
When someone asks an assistant "find me a room near the hospital for three nights next week, under a hundred a night", the assistant has three jobs. It answers questions: the price, whether tax is on top, whether pets are allowed, what happens if plans change. It compares rooms. And at the end it hands the guest a link to finish the booking.
That last step matters. The guest should press the button, not the assistant. A good lodging site makes the handoff easy and honest: the link opens the right form with the right dates, the prices mean what they appear to mean, and the policy the guest is agreeing to is one click away for both of them. Six things make that work.
1. A booking link that opens the form filled in
Most hotel sites publish a booking URL with nothing in it. An assistant that has spent five messages agreeing on dates and a room type can only say "go here and start over". If your booking page already reads its fields from the query string (many do, so that "check availability" widgets work), say so in the markup.
Schema.org's ReserveAction takes a target that is an EntryPoint, and an EntryPoint can carry a urlTemplate, an RFC 6570 template with placeholders in braces. The result of the action can be a LodgingReservation, which has checkinTime, checkoutTime and lodgingUnitType. Schema.org's action vocabulary also lets you say which input fills which form field, with a property name followed by -input:
"potentialAction": {
"@type": "ReserveAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "https://examplemotel.com/reserve?type={type}&checkin={checkin}&checkout={checkout}",
"actionPlatform": ["https://schema.org/DesktopWebPlatform", "https://schema.org/MobileWebPlatform"]
},
"result": {
"@type": "LodgingReservation",
"lodgingUnitType-input": "name=type",
"checkinTime-input": "name=checkin",
"checkoutTime-input": "name=checkout"
}
}
Then document the same parameters wherever agents read: a line in llms.txt ("To open the booking form filled in, use https://examplemotel.com/reserve?type=double&checkin=2026-11-03&checkout=2026-11-06"), the same in AGENTS.md if you publish one, and a booking.prefill entry in any rates file you publish.
One rule makes this safe: the link only fills in the form. It must not hold a room, start a reservation or charge anything. A link is a GET request, and HTTP defines GET as a safe method, one where "the client does not request, and does not expect, any state change on the origin server". Crawlers, link previews and security scanners follow links all day. If following one could hold a room, they would.
And one thing to never do: point the booking action at a contact page or a waitlist. An agent that follows it lands somewhere that cannot take a booking and may tell the guest the property is not bookable online.
2. A cancellation policy the assistant can reach
Guests ask about cancellation before they book. An assistant that cannot find your policy either guesses or says nothing, and both are worse than quoting your own words.
The common trap is reasonable on its own. Policy pages are thin and legal, so many sites mark them noindex to keep them out of search results. Google drops a noindexed page from its results entirely, and an answer engine that builds on a search index has nothing there to retrieve. The page still exists, but nothing points an agent at it.
The fix costs one line: name the policy URL in llms.txt, and in AGENTS.md and your rates file if you publish them (a policies.cancellation key works). The page can stay noindex. An agent reading your agent files can fetch it directly. Link it from the booking page as well, since that is where the guest needs it.
3. Manifests that say what they point at
Plenty of sites carry an ai-plugin.json, the manifest format from ChatGPT's old plugin system. Its api member names an API description, and in OpenAI's own example it looks like "api": {"type": "openapi", "url": "http://localhost:5003/openapi.yaml"}.
A pattern I keep finding is a site with no API that still fills in the api member, pointing it at llms.txt. That is a plain-text guide for language models, not an OpenAPI document. The OpenAPI specification says the document's openapi field is required, and llms.txt has none. A client that trusts the label tries to parse your guide as an API description, fails, and learns that your site misdescribes itself.
If you have no OpenAPI document, drop the api member. The manifest's description fields and llms.txt still carry everything an agent needs. I found this exact mistake on jwatte.com while writing these checks, and removed it in the same release.
4. A booking page that makes a link preview
The booking link is the one a guest is most likely to receive in a text message or a chat, often from the assistant itself. Booking pages are also the pages most likely to be built as bare forms with no Open Graph tags, because nobody thinks of a form as something people share.
Without og:title, og:image and twitter:card on the page, the link arrives as a bare address. With them, it arrives as a card with your property's name and a photo, which reads as a real business rather than a suspicious URL. The Open Graph protocol lists title, type, image and URL as the four required properties for every page. If your booking hub is a page that lists several properties, it needs the tags as much as each property's own form does.
5. Prices that say whether tax is included
Lodging prices are almost always quoted before occupancy and sales tax. The page usually says so in small type: "$129 a night, before 12% tax". The markup usually does not.
Schema.org's valueAddedTaxIncluded is the property for this. It says whether the applicable tax is included in a price specification, and it is a plain true or false on every PriceSpecification and UnitPriceSpecification:
"priceSpecification": {
"@type": "UnitPriceSpecification",
"price": 129,
"priceCurrency": "USD",
"unitCode": "DAY",
"valueAddedTaxIncluded": false
}
When the page says "before tax" and the markup is silent, an assistant reading the markup has no way to know the total is higher, and it may quote $129 as what the guest will pay. When the markup says true and the page says "plus tax", the two disagree, and the markup is the one the agent reads. Either way the guest finds out at the desk.
6. Room offers priced per night or per week
An assistant comparing rooms needs to know which price belongs to which room, and per what. A single price on the business node does not say either.
Model each room type as an Offer whose itemOffered is a HotelRoom (or another Accommodation type), and give the price a unit. unitCode takes UN/CEFACT Common Codes, where DAY is a day, WEE a week and MON a month. If a stay has a minimum or a maximum length, eligibleDuration puts that limit in the offer instead of leaving it in a sentence:
{
"@type": "Offer",
"itemOffered": { "@type": "HotelRoom", "name": "Double room" },
"priceSpecification": [
{ "@type": "UnitPriceSpecification", "price": 129, "priceCurrency": "USD", "unitCode": "DAY", "valueAddedTaxIncluded": false },
{ "@type": "UnitPriceSpecification", "price": 690, "priceCurrency": "USD", "unitCode": "WEE", "valueAddedTaxIncluded": false }
],
"eligibleDuration": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 30, "unitCode": "DAY" }
}
Weekly and extended-stay properties benefit most. A nightly rate and a weekly rate on the same room are two different offers, and without a unit an agent can only guess which number is which.
What I deliberately left out
Some things a retail checklist asks for are wrong for lodging, and adding them would make the site worse:
- No Product markup on rooms. A room is a place with dates, not an item with a barcode.
- No booking tool for agents. If your site runs an MCP server, keep it read-only and mark its tools with
readOnlyHint. An assistant can check availability and quote a price; the guest submits the booking. - No payment or checkout protocol files. Nothing on a typical lodging site is paid for by an agent.
- No OAuth metadata for an API that is public. The 404 is the correct answer.
What the checks look like now
The Mega Analyzer's Hotel / lodging readiness card has a new "Agent booking readiness" section with one row for each fix above. It runs when the page carries a lodging type anywhere in its JSON-LD (a top-level Motel, a HotelRoom nested inside an offer, or a node typed in one block and referred to by @id in another), when the page reads as lodging with booking signals, or when you set the business type to Local-Hospitality in the audit alignment bar. Missing surfaces are reported as information, not failures: plenty of good hotel sites publish no llms.txt. The red rows are reserved for things that mislead: a booking action aimed at a contact page, a price marked tax-included on a page that says "plus tax", or markup that drops the "before tax" the page itself states.
The Agent Endpoint Inspector checks the same ground from the agent's side. On any site, it flags an ai-plugin.json that calls something OpenAPI when it is not. On booking sites, it checks whether the booking link's parameters are documented and whether the agent files name a cancellation policy that actually answers. It reads files only. It never submits a form and never calls an MCP tool.
I tested both against the three lodging sites before and after their fixes, three hotel property pages (two of them from large brands), and a set of stores, restaurants and service businesses. The hotel pages showed the same gaps the small sites had: bare booking URLs and, on one of them, a price specification with no tax flag. The stores, restaurants and service businesses got no new rows at all. The checks only ask lodging questions of lodging sites.
If you want the wider picture of getting a small business cited and recommended by AI assistants without paying an agency for it, The $20 Dollar Agency covers it end to end.
Fact-check notes and sources
- ReserveAction, EntryPoint and urlTemplate: schema.org/ReserveAction, schema.org/EntryPoint and schema.org/urlTemplate ("An url template (RFC6570)").
- The
-inputannotations: schema.org Actions overview, which describes input and output annotations using a hyphen delimiter, such aslocation-input. - LodgingReservation: schema.org/LodgingReservation (checkinTime, checkoutTime, lodgingUnitType).
- Safe methods: RFC 9110, section 9.2.1, quoted above.
- noindex: Google Search Central, Block Search indexing with noindex: Google drops a page with the rule "entirely from Google Search results".
- ai-plugin.json: OpenAI's plugins quickstart manifest shows the
apimember with"type": "openapi"pointing at an OpenAPI YAML file. OpenAI's original plugin documentation no longer exists at its old address. - OpenAPI's required field: OpenAPI Specification: "openapi: REQUIRED. This string MUST be the version number of the OpenAPI Specification that the OpenAPI document uses."
- Open Graph: ogp.me: "The four required properties for every page are" og:title, og:type, og:image and og:url.
- Tax flag: schema.org/valueAddedTaxIncluded: "Specifies whether the applicable value-added tax (VAT) is included in the price specification or not."
- Units: schema.org/unitCode ("The unit of measurement given using the UN/CEFACT Common Code (3 characters) or a URL") and schema.org/UnitPriceSpecification. The code list itself is UN/CEFACT Recommendation 20; the UNECE recommendations page would not open for me, so I read it through an archived copy from December 2024.
- Stay limits and rooms: schema.org/eligibleDuration ("The duration for which the given offer is valid"), schema.org/HotelRoom and schema.org/itemOffered.
- Read-only MCP tools: the MCP schema reference defines
readOnlyHintamong the tool annotations, and notes that all of them are hints. - llms.txt and AGENTS.md: llmstxt.org and agents.md.
- My measurements: the 37 to 51 percent scores, the 27 of 70 retail-only points and the 61 to 64 percent ceiling come from running my own Agentic Commerce Readiness tool against three lodging sites on October 15, 2026, and reading its scoring code.
Related reading
- Hotels ship the schema and forget the listings
- Making a small business site agent ready: what broke, what held, and what to copy
- One CORS header, 28 sites: the redeploy discipline behind a one-line fix
- Agent readiness past llms.txt: eleven files, and the five that silently fail validation
- Three direct-booking patterns that don’t break OTA rate parity
This post is informational, not legal or SEO-consulting advice. Tax rules for lodging vary by state and city; check yours before you publish a price. Mentions of schema.org, OpenAI, Google, the OpenAPI Initiative, the Open Graph protocol, X, UNECE and other parties are nominative fair use. No affiliation is implied.