Fixing Event, Job and Product Rich Results
Events, job adverts and products are the three kinds of page where rich results still matter most for ordinary businesses: an event can appear in Google's event listings with its date and venue, a vacancy can appear in Google's job search, and a product can show its price and availability.
Each type has a short list of fields Google will not do without, plus a few time-sensitive rules that catch people out, such as expired dates and the wrong time zone. This guide gives the minimum working markup for each, the mistakes that lose eligibility, and how to keep listings current.
One page, one thing: choosing the right type
All three rich results assume that a page is about one specific item. Most eligibility problems for these types start with markup on the wrong kind of page.
| Page | Right markup | Common mistake |
|---|---|---|
| A single gig, class, match, workshop or webinar at a set time | Event | Marking the venue's "What's on" listing page as one Event |
| A series such as a weekly quiz night | One Event per date, each with its own
page or entry | One Event with a start date months ago and an end date next year |
| A sale, voucher or opening hours | No Event markup; this is not an event | Marking "Summer sale, 1 to 31 July" as an Event |
| A single vacancy | JobPosting | Marking a "Careers" page that lists several roles as one JobPosting |
| A recruitment agency's general "register with us" page | No JobPosting | Inventing a vacancy to get into job listings |
| A product you sell or review | Product | Marking a category or collection page as a Product |
Google's event documentation is clear that promotions and time-limited offers are not events, and its job posting guidelines require a real vacancy that people can apply for. Markup on the wrong page is not just ineligible; it can count as spammy structured data.
Event: the minimum that works
Google requires three things for an event rich result: name, startDate and
location. Almost everything else is recommended, but several recommended fields make a real
difference to how the listing looks and to whether people trust it.
| Field | Status | Notes |
|---|---|---|
name | Required | The event title only, not "Tickets for..." or the venue name. |
startDate | Required | ISO 8601 date and time with a UTC offset. |
location | Required | A Place with an address for in-person
events, a VirtualLocation with a url for online ones, or both for hybrid. |
endDate | Recommended | Same format as the start. |
eventStatus | Recommended | EventScheduled, EventCancelled,
EventPostponed, EventRescheduled or EventMovedOnline. |
eventAttendanceMode | Recommended | OfflineEventAttendanceMode,
OnlineEventAttendanceMode or MixedEventAttendanceMode. |
offers | Recommended | Ticket price, currency, availability, the ticket URL and when sales open. |
image, description, organizer, performer | Recommended | What makes the listing recognisable. |
A working in-person event
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Beginners' Sourdough Workshop",
"description": "A three-hour hands-on class covering starters, shaping and baking. All ingredients provided.",
"startDate": "2026-11-14T10:00:00+00:00",
"endDate": "2026-11-14T13:00:00+00:00",
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"location": {
"@type": "Place",
"name": "Millrace Bakery School",
"address": {
"@type": "PostalAddress",
"streetAddress": "4 Wharf Lane",
"addressLocality": "Bakewell",
"postalCode": "DE45 1AA",
"addressCountry": "GB"
}
},
"image": ["https://example.co.uk/images/sourdough-class-16x9.jpg"],
"organizer": { "@type": "Organization", "name": "Millrace Bakery School", "url": "https://example.co.uk" },
"offers": {
"@type": "Offer",
"url": "https://example.co.uk/classes/sourdough-14-nov",
"price": "65.00",
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"validFrom": "2026-09-01T09:00:00+01:00"
}
}
</script>
Note the +00:00 offset: 14 November is after the clocks go back, so UK times are on GMT.
The ticket sale date in September uses +01:00 because it falls in British Summer Time.
Online and hybrid events
For a webinar, set eventAttendanceMode to online and give location as a
VirtualLocation with the joining or registration URL. For a hybrid event, use mixed attendance
and supply location as an array containing both the Place and the VirtualLocation.
JobPosting: the minimum that works
Job posting markup feeds Google's job search experience. The required fields are title,
description, datePosted, hiringOrganization and jobLocation,
with one exception for fully remote roles. validThrough is required when the advert has
a closing date, and baseSalary, employmentType, identifier and
directApply are recommended.
- title is the job title only. "Senior Bookkeeper" is right; "Senior Bookkeeper, Leeds, ยฃ32k, apply now!!" is not.
- description must be the full advert, and it can contain simple HTML such as paragraphs and lists, which the other text fields cannot.
- hiringOrganization is the employer. An agency advertising for a named client should name the client if it can; if the client is confidential, the agency may use its own name.
- Remote roles use
jobLocationTypeset toTELECOMMUTEplusapplicantLocationRequirementsnaming the country or region applicants must live in. A hybrid role still needs its officejobLocation.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Part-time Bookkeeper",
"description": "<p>Keep the accounts for a busy family-run garden centre, three days a week.</p><ul><li>Purchase and sales ledgers</li><li>VAT returns</li></ul>",
"identifier": { "@type": "PropertyValue", "name": "Fernbrook Garden Centre", "value": "FB-2026-014" },
"datePosted": "2026-09-22",
"validThrough": "2026-10-20T23:59:00+01:00",
"employmentType": "PART_TIME",
"hiringOrganization": { "@type": "Organization", "name": "Fernbrook Garden Centre", "sameAs": "https://example.co.uk" },
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "Old Road",
"addressLocality": "Matlock",
"postalCode": "DE4 3AA",
"addressRegion": "Derbyshire",
"addressCountry": "GB"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "GBP",
"value": { "@type": "QuantitativeValue", "minValue": 15, "maxValue": 17, "unitText": "HOUR" }
},
"directApply": true
}
</script>
lastmod dates is usually enough.Product: the short version
Product markup is covered in depth in the Product
schema errors guide, so only the eligibility minimum is repeated here. Product snippets need a name
plus at least one of offers, review or aggregateRating. Merchant
listings, the shopping-style results, need name, image and an offers
object with price and priceCurrency, and they only apply to pages where the
visitor can buy from you.
The quick checks that fix most product eligibility problems: the price is a plain number without a
currency symbol; the currency is a three-letter code such as GBP; availability is a full
schema.org URL; and the price in the markup is the same as the price on the page. If you add ratings,
the separate guides on aggregateRating
errors and review snippets cover
the rules.
Dates, times and the UK clock change
Date handling is the most common reason an event or job goes wrong after it has been marked up correctly once. Google reads ISO 8601, and the offset matters.
- Always include an offset.
2026-11-14T10:00:00with no offset leaves Google guessing the time zone. Add+00:00in winter or+01:00in summer for UK events. - Watch the clock change. Templates that hard-code
+01:00put every winter event an hour out. Generate the offset from the event's actual date using your server's time zone database, set to Europe/London. - Date-only is acceptable for all-day events and for
datePosted, but do not append midnight with a wrong offset. - Keep the page and the markup in step. If the page says "Doors 7pm, show 8pm", pick
one for
startDateand use it consistently.
Wrong: "startDate": "14/11/2026 10am"
Wrong: "startDate": "2026-11-14T10:00:00+01:00" (summer offset in November)
Right: "startDate": "2026-11-14T10:00:00+00:00"
Cancellations, postponements and expiry
Events and jobs are time-limited, so the markup needs maintaining after publication. Stale items are one of the policy problems that can cost rich results.
Events that change
- Cancelled: keep the page and the original
startDate, and seteventStatustoEventCancelled. Do not delete the page straight away; people will still search for it. - Postponed with no new date: set
EventPostponedand leave the original date in place. - Rescheduled: set
EventRescheduled, put the new date instartDateand the old one inpreviousStartDate. - Moved online: set
EventMovedOnline, change the attendance mode and add aVirtualLocation.
Jobs that close
When a vacancy is filled or closed, do one of these the same day: remove the page so it returns a
404 or 410, add noindex, or remove the JobPosting markup. Updating validThrough
to a past date also tells Google the advert has expired. Leaving closed jobs marked up as open is a clear
breach of Google's job posting guidelines and can lead to a manual action.
endDate has passed.The fix, step by step
Step 1
Pick the right type for each page
List the templates that carry Event, JobPosting or Product markup and confirm each one describes a single item. Listing pages, category pages, careers overviews, sales and vouchers should not carry these types at all. Remove the markup from any template that describes many items or something that is not really an event, vacancy or product, and make sure each individual item has its own page or its own clearly separate entry.
Step 2
Fill the required fields for Event
Every
Event needs name, startDate and location. For venues, give a Place
with a full PostalAddress including postcode and country; for online events, a VirtualLocation
with a URL. Then add the recommended fields that improve the listing: endDate, eventStatus,
eventAttendanceMode, an image, a description, the organiser and an offers object
with the ticket price and link, so the listing shows what the event costs and where to book.
Step 3
Fill the required fields for JobPosting
Every
JobPosting needs title, the full advert in description, datePosted,
the employer in hiringOrganization and a jobLocation with a postal address.
For fully remote roles, replace the location with jobLocationType set to TELECOMMUTE
and applicantLocationRequirements. Add validThrough when there is a closing
date, and include salary and employment type wherever you can show them honestly, because applicants
filter by both in job search.
Step 4
Check Product has an offer, review or rating
Open a product page in the Rich Results Test and confirm that each Product has a name
and at least one of offers, review or aggregateRating. For merchant
listings, also confirm an image and an offer with a plain numeric price and a three-letter
priceCurrency. Make sure the price in the markup matches the price a visitor sees, including
any sale price shown on the page.
Step 5
Get dates and time zones right
Write
every date in ISO 8601 with a UTC offset, and generate the offset from the item's own date rather than
hard-coding it, so winter events use +00:00 and summer events +01:00. Check
startDate, endDate, validFrom, datePosted and validThrough
on a winter item and a summer item. Make sure the times in the markup match the times printed on the
page exactly.
Step 6
Handle cancelled, moved and expired items
Set eventStatus whenever an event is cancelled, postponed, rescheduled or moved
online, and add previousStartDate when the date changes. For jobs, remove the page, add
noindex or drop the markup on the day the vacancy closes. Build these rules into your templates
or CMS workflow so they happen automatically, instead of relying on someone remembering to edit old pages
later.
Step 7
Test each template and request indexing
Run one URL for each template through the Rich Snippets Suite and the Rich Results Test, and fix anything reported as an error before looking at warnings. Then check the Event, Job postings, Product snippets or Merchant listings report in Search Console, press Validate fix on any open issue and request indexing for your most important pages. Re-test after every template change or plugin update.
Where this markup usually comes from
- WordPress: event calendar plugins and job board plugins usually output their own markup. Check that only one plugin produces each type, and that its time zone setting matches the site's general settings.
- Ticketing platforms: if tickets are sold through a third-party platform, its event page may already carry Event markup. Your own page can still carry markup for the same event, but both should agree on dates and venue.
- Applicant tracking systems: many hosted careers pages output JobPosting automatically. If your own site also lists the job, decide which page is the main one and avoid two conflicting versions.
- Shop platforms: Product markup normally comes from the theme. See the Shopify rich snippets guide for store-specific problems.
1. What are the required fields for Event rich results?
Google requires three: name, startDate and location. The location can be a Place with a full postal address for an in-person event, a VirtualLocation with a URL for an online one, or both for a hybrid event. Google also recommends endDate, eventStatus, eventAttendanceMode, image, description, organizer, performer and offers. The required three make the event eligible, but the recommended ones decide how useful and trustworthy the listing looks to searchers.
2. Why is my event not showing in Google's event listings?
First check that the page describes one event with a future date and that the markup passes the Rich Results Test. Common faults are a listing page marked up as one event, a missing address, a date without a time zone offset, and sales or vouchers marked up as events, which Google excludes. Even with valid markup, Google chooses which events to show for each search, so a correct page is eligible but not guaranteed to appear.
3. Can I mark up a recurring event such as a weekly class?
Yes, but mark up each occurrence as its own Event with its own start date, rather than one Event spanning months. Each occurrence can have its own page, or a single page can carry several Event entries if each date is clearly shown to visitors. A single Event with a start date in the past and an end date far in the future describes something that is not really an event, and it is unlikely to be shown.
4. How should I mark up a remote job?
Set jobLocationType to TELECOMMUTE and add applicantLocationRequirements naming the country or region where applicants must be based, for example the United Kingdom. For a fully remote role you can leave out jobLocation. For a hybrid role, where people must attend an office some of the time, keep the office jobLocation as well as the telecommute setting, so Google knows both that remote work is possible and where the office is.
5. What should I do with job adverts once the vacancy is filled?
Take the advert out of Google's job listings on the day it closes. You can remove the page so it returns a 404 or 410 status, add a noindex tag, or remove the JobPosting markup. Setting validThrough to a date that has passed also signals expiry. Leaving closed vacancies marked up as open is against Google's job posting guidelines, frustrates applicants and can lead to a manual action that affects all your job pages.
6. Why does my event show the wrong time in Google?
Almost always because of the time zone offset. A date without an offset leaves Google to guess, and a template that always writes +01:00 puts every winter event an hour out, because the UK is on GMT from late October to late March. Generate the offset from each event's own date using the Europe/London time zone, and make sure the time in the markup matches the time printed on the page.
7. Do I need Product markup on every page that mentions a product?
No. Product markup belongs on the page that is about one product, such as its product detail page or a dedicated review of it. Category pages, blog posts that mention several products and comparison round-ups should not carry a Product block for each item they mention. Put the effort into making each product page's markup complete, with a correct price, currency, availability and image, since those pages are the ones that can earn product results.
The Rich Snippets Suite identifies every rich result type a page is eligible for, validates the schema, previews how the result could look and tracks the rich result coverage your pages get in Google over time.
Open Rich Snippet Fixes โ