Event Schema Markup: Getting Events Into Google's Rich Results
- November 16, 2023
- Technical SEO
Event-rich results turn a plain blue link into a date-stamped, location-aware listing that can surface in Google Search and the dedicated event experience on mobile. The payoff is real, but Google is strict: malformed dates, missing offers, or vague locations either suppress the rich result or trip a manual action. This guide walks through implementing event structured data that actually validates and earns enhanced listings, with the edge cases that trip up most teams.
What Google Actually Requires
Google supports the Event type from Schema.org, plus its subtypes (MusicEvent, BusinessEvent, SportsEvent, TheaterEvent, and others). Use the most specific subtype that fits—it costs nothing and helps disambiguation. Required and recommended properties break down like this:
- Required:
name,startDate, andlocation. - Strongly recommended:
endDate,eventStatus,eventAttendanceMode,image,description,offers, andorganizer.
Use JSON-LD in a <script type="application/ld+json"> block. It is the format Google recommends, it decouples markup from your visual HTML, and it is far easier to template and debug than Microdata. One critical rule: the structured data must describe content visible on the page. Marking up an event the user can't see is a policy violation.
Dates and Time Zones: Where Most Implementations Break
Dates are the single biggest source of errors. startDate and endDate must be in ISO 8601 format, and you should always include the time and the UTC offset. A date with no offset forces Google to guess the time zone, which produces wrong listings for users in other regions.
- Correct:
"startDate": "2026-09-14T19:00:00-04:00" - Risky:
"startDate": "2026-09-14"(date-only is valid but loses the start time and ordering precision) - Wrong:
"startDate": "09/14/2026 7:00 PM"(not ISO 8601—will fail validation)
Derive the offset from the venue's local time zone, not your server's. An event in Los Angeles uses -08:00 (or -07:00 during daylight saving), regardless of where your CMS runs. For recurring events, do not cram a series into one item. Emit a separate Event object per occurrence, each with its own startDate, or use the repeating-event structures Google documents. A single object can only own one start time.
Location: Physical, Virtual, and Hybrid
The shape of location depends on eventAttendanceMode. Getting this pairing right is what separates a clean validation from a warning.
In-person events
Set eventAttendanceMode to https://schema.org/OfflineEventAttendanceMode and provide a Place with a full PostalAddress. Spell out every address component—streetAddress, addressLocality, addressRegion, postalCode, addressCountry. A bare city name weakens the result.
Virtual events
Set the mode to OnlineEventAttendanceMode and make location a VirtualLocation with a url pointing to where people actually attend (the stream or webinar page), not your homepage:
"location": { "@type": "VirtualLocation", "url": "https://example.com/live/keynote" }
Hybrid events
Use MixedEventAttendanceMode and supply both location objects in an array—a Place for the physical venue and a VirtualLocation for the stream. Omitting either one for a hybrid event is a common validation warning.
Tickets and Offers
The offers property is what makes a listing feel actionable, and it is heavily favored for the event experience. Include it whenever pricing exists:
priceandpriceCurrency(ISO 4217, e.g."USD"). For free events, use"price": "0".availabilityusing a schema URL:https://schema.org/InStockorhttps://schema.org/SoldOut.urlpointing to the actual ticket-purchase page, not the event landing page.validFromas the ISO 8601 datetime sales open—useful for pre-sale windows.
For tiered pricing (general admission, VIP, early bird), provide an array of Offer objects. Don't fake a single average price; list the real tiers or use the lowest available price with the correct availability state.
Status, Cancellations, and Postponements
The eventStatus property exists precisely so Google can show accurate badges. Always set it, and update it the moment plans change:
EventScheduled— the default, proceeding as planned.EventCancelled— keep the page and markup live; don't delete it.EventPostponed— date unknown; leave the oldstartDateuntil you have a new one.EventRescheduled— updatestartDateto the new date and addpreviousStartDate.EventMovedOnline— pair with a switch ofeventAttendanceModeto online and aVirtualLocation.
A Minimal Valid Example
This in-person event passes validation and carries the recommended fields:
"@context": "https://schema.org", "@type": "MusicEvent""name": "Autumn Sessions: Live""startDate": "2026-09-14T19:00:00-04:00", "endDate": "2026-09-14T22:30:00-04:00""eventStatus": "https://schema.org/EventScheduled""eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode""location": { "@type": "Place", "name": "Riverside Hall", "address": { "@type": "PostalAddress", "streetAddress": "120 River St", "addressLocality": "Portland", "addressRegion": "ME", "postalCode": "04101", "addressCountry": "US" } }"image": ["https://example.com/event-16x9.jpg"]"offers": { "@type": "Offer", "url": "https://example.com/tickets", "price": "35", "priceCurrency": "USD", "availability": "https://schema.org/InStock", "validFrom": "2026-07-01T09:00:00-04:00" }"organizer": { "@type": "Organization", "name": "Autumn Live", "url": "https://example.com" }
Common Mistakes
- Date-only when you know the time. If your page shows "7:00 PM," your markup should too. Date-only loses ordering and start-time display.
- Server time zone leakage. Offsets must reflect the venue, not your hosting region.
- Marking up event aggregators or listing pages as a single event. Each event needs its own item; a category page listing twenty events should mark up each one, not invent a wrapper event.
- Pointing
url/offerurlat the wrong page. Offer URLs go to checkout; virtual location URLs go to the stream. - Forgetting the schema.org prefix on enum values.
InStockalone is invalid; it must be the fullhttps://schema.org/InStockURL. - Mismatched markup and page content. Hidden or contradictory data risks a manual action.
- Deleting cancelled events. Keep the URL live with
EventCancelledso users searching the event get the accurate status instead of a 404.
Testing and Deployment
Before shipping, run every template through Google's Rich Results Test to confirm the page is eligible and to catch errors versus warnings—errors block the result, warnings degrade it. Use the Schema Markup Validator for spec-level correctness. After deployment, monitor the Events enhancement report in Search Console, which surfaces field-level errors at scale across your live URLs and tracks valid items over time. Rich results are never guaranteed even with perfect markup, but accurate, complete, page-matching data is the prerequisite—and it is the part fully within your control.
Want this handled properly on your site?
It is exactly the kind of work an advanced technical SEO audit covers. See how an advanced SEO audit works →
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.








