Somebody validates your Product markup, Google’s testing tool returns no errors, and everyone concludes the work is done.
Then six months pass and no star rating has ever appeared next to your menu, no price has shown in a result, and nothing in Search Console suggests a rich result was ever eligible. The markup is correct. It is also inert.
This is one of the few SEO tasks where the tool telling you it is valid and Google actually using it are almost unrelated, and the gap costs dispensary teams a great deal of pointless work.
Validation is not eligibility
Structured data has two separate tests and teams routinely run only the first.
Is it valid? Does the JSON parse, do the required properties exist, are the types correct. A validator answers this, and the answer is usually yes because the generator that produced it was built properly.
Is it eligible? Will Google use it to produce a rich result for this page, in this category, in this country. Nothing in a validator answers this, because it is a policy question rather than a technical one.
Cannabis sits inside Google’s restricted categories. Shopping surfaces, product rich results, and merchant features are not available to plant-touching retailers, regardless of how legal you are in your state and regardless of how correct your markup is.
So the Product schema on your menu passes test one and fails test two, silently, forever.
The second problem, which is worse
If the markup did nothing at all, this would be a story about wasted time.
The reason to actually remove it is different: marking up cannabis products with prices, potency, and availability makes your page look like it is selling restricted goods, in a machine-readable format, on a surface Google reads carefully.
That is the same behaviour that gets a Business Profile pulled when somebody adds products to a listing. It is not an argument that Product schema on a menu page will trigger enforcement, and I want to be careful not to overstate it. But you are volunteering a structured declaration of exactly the thing the policies restrict, in exchange for a rich result that cannot appear.
The trade is bad in both directions. No upside, some downside, and a validator that reassures you the whole time.
What actually works on a dispensary site
Three types, in order of how much they return.
LocalBusiness, or better, Store. This is the one that earns its place. It states your name, address, coordinates, hours, and phone in a form that does not depend on rendering at all, which matters enormously on a site where the menu often does not reach the HTML. Every location page should carry it, with its own address and its own coordinates.
FAQPage. Still eligible, still capable of producing an enhanced result, and genuinely useful on location pages and guides where you are answering the questions people ask before visiting. Mark up questions you actually answer on the page, not questions you invented to get the markup.
Article or BlogPosting on your guides and posts. It will not usually produce a visible enhancement on its own, but it establishes authorship and dates cleanly, which matters for a site whose credibility rests on a named person having written the material.
What to avoid, and why each one
Product, ProductGroup, and Offer on cannabis items. Covered above. No rich result available, and a structured declaration you would rather not make.
HealthAndBeautyBusiness or Pharmacy as your business type. These sound more specific and therefore better. They imply a healthcare context, which invites a stricter reading of everything else on the page, and they are simply inaccurate for a recreational retailer. Store is the honest choice and the safe one.
Review and AggregateRating that you control. Self-serving review markup has not produced rich results for a long time, and marking up ratings you host yourself is exactly the pattern the guidelines call out. Your reviews belong on your Business Profile, where they do real work.
Anything describing content that is not on the page. This is the guideline people break most often without noticing. If your hours are in the schema they must be visible to a visitor. Markup describing something a human cannot see is a violation, not a shortcut.
Generate markup that is actually eligible
The dispensary schema generator builds valid LocalBusiness JSON-LD with grouped hours, coordinates, and cannabis-specific fields, and leaves out the types that cannot produce a result for this category.
Open the dispensary schema generator
The mistake I find most often
It is not missing markup. Sites without schema are easy to spot and easy to fix.
The most common finding is markup that was correct on the day a developer added it and has quietly disagreed with the page ever since.
A store changes its Sunday hours. Somebody updates the visible hours table on the page, because that is what customers read. The JSON-LD in the header, added during the original build, still says the old times.
On one chain, four of eleven stores had schema hours that no longer matched the page. Nobody had touched the markup in two years, because nobody thought of it as content.
That is the framing worth adopting: schema is content, not a technical task you complete. It goes stale exactly the way a paragraph goes stale, and it has no visible symptom when it does.
How to check yours in ten minutes
1. Open a location page and view source. Find the JSON-LD block. Read the address, the hours, and the phone number, then compare each one against what is visible on the same page. Mismatches are the most common fault and the easiest to fix.
2. Check the coordinates against the storefront. Right click your store pin in Google Maps and compare. A surprising number of sites carry the city centre coordinates on every location, which defeats the purpose of including them.
3. Search your source for the types you should not have. Look for Product, Offer, AggregateRating, and HealthAndBeautyBusiness. If a menu plugin added them, they will be there without anyone having decided.
4. Confirm every location page has its own block. The failure at scale is generating the markup once and reusing it across thirty pages with only the city changed, which produces thirty stores claiming the same coordinates.
5. On a chain, add parentOrganization so each Store connects to the brand entity rather than sitting as thirty unrelated businesses.
Do not add schema to compensate for content Google cannot read.
This comes up on sites with invisible menus. The reasoning is that if the products cannot be crawled, marking them up will tell Google what is there anyway.
It does not work, and it makes the underlying problem harder to see. Schema describes content that exists on the page. It is not a substitute for the content existing.
Why this matters more here than elsewhere
On an ordinary retail site, schema is a modest enhancement layer over a page Google can already read perfectly well.
On a dispensary site it is doing something different. If your menu renders through an iframe or arrives after JavaScript, the crawler’s view of your location page can be close to empty. LocalBusiness markup is then one of the few unambiguous statements it receives about what the page is and where the business sits. Markup is the workaround, though. Getting the menu itself into the HTML is the fix.
That is a real reason to get it right. It is also a reason not to over-invest: markup that describes a page with nothing on it does not create the missing content. Fix delivery first, then let the schema describe a page worth describing.
What to do this week
If you have Product schema on your menu, remove it. Nothing will drop, because nothing was being produced from it.
Then check one location page against the five steps above. Whatever you find there is almost certainly true of the rest, because these are template problems rather than page problems, and fixing the template fixes all of them at once.
If you take one thing away
Valid and eligible are different questions. Mark up the business and the questions you answer. Do not mark up the products.
