EventSchema
Outputs an Event with venue, online location, tickets, organizer and performer; use it on pages for concerts, meetups, conferences and webinars.
EventSchema describes one event. It outputs an Event whose
location is a Place, a
VirtualLocation or both, depending on the attendance
mode, and targets Google’s
event experience
(date, place and tickets in event listings).
Usage
An event page rendered from a content collection. If the frontmatter uses the prop names,
the collection schema can be eventZodSchema, so wrong data is reported where it is written
(see Zod schemas and content). Here the frontmatter has
its own field names, mapped to the props in the page:
# src/content/events/astro-meetup-berlin.md (frontmatter)
name: Astro Meetup Berlin
description: Talks on content collections and structured data, followed by drinks.
startDate: '2026-11-19T18:30:00+01:00'
endDate: '2026-11-19T22:00:00+01:00'
image: /images/events/meetup.jpg
venue: Hub Berlin
address:
streetAddress: Alexanderplatz 1
addressLocality: Berlin
postalCode: '10178'
addressCountry: DE
ticketPrice: 15
speaker: Jane Doe
---
// src/pages/events/[slug].astro
import { getCollection } from 'astro:content';
import { EventSchema } from '@casoon/astro-structured-data/components';
export async function getStaticPaths() {
const events = await getCollection('events');
return events.map((event) => ({ params: { slug: event.id }, props: { event } }));
}
const { data } = Astro.props.event;
---
<EventSchema
name={data.name}
description={data.description}
startDate={data.startDate}
endDate={data.endDate}
imageUrl={data.image}
locationName={data.venue}
locationAddress={data.address}
price={data.ticketPrice}
priceCurrency="EUR"
availability="InStock"
organizer={{ name: 'Astro Berlin', url: 'https://example.com' }}
performer={{ name: data.speaker }}
/>
Quote date-times in YAML. Unquoted, YAML may turn them into Date objects, which are output
in UTC (2026-11-19T17:30:00.000Z) instead of with the offset as written.
Output
On /events/astro-meetup-berlin/:
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Astro Meetup Berlin",
"startDate": "2026-11-19T18:30:00+01:00",
"endDate": "2026-11-19T22:00:00+01:00",
"description": "Talks on content collections and structured data, followed by drinks.",
"image": [
"/images/events/meetup.jpg"
],
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"eventStatus": "https://schema.org/EventScheduled",
"location": {
"@type": "Place",
"name": "Hub Berlin",
"address": {
"@type": "PostalAddress",
"streetAddress": "Alexanderplatz 1",
"addressLocality": "Berlin",
"postalCode": "10178",
"addressCountry": "DE"
}
},
"offers": {
"@type": "Offer",
"price": 15,
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"url": "https://example.com/events/astro-meetup-berlin/"
},
"organizer": {
"@type": "Organization",
"name": "Astro Berlin",
"url": "https://example.com"
},
"performer": {
"@type": "Person",
"name": "Jane Doe"
}
}
attendanceModedefaults toOfflineandstatustoScheduled; both are output as schema.org URLs.- The ticket offer links to
urlwhen set, otherwise to the current page. imageUrlis always output as an array; root-relative paths are written as given.
Online event
An online event has no venue. Its onlineUrl becomes a VirtualLocation:
<EventSchema
name="Astro Live Webinar"
description="Structured data in Astro, live with Q&A."
startDate="2026-10-20T17:00:00+02:00"
endDate="2026-10-20T18:30:00+02:00"
attendanceMode="Online"
onlineUrl="https://example.com/live"
organizer={{ name: 'Example GmbH', url: 'https://example.com' }}
price={0}
priceCurrency="EUR"
/>
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Astro Live Webinar",
"startDate": "2026-10-20T17:00:00+02:00",
"endDate": "2026-10-20T18:30:00+02:00",
"description": "Structured data in Astro, live with Q&A.",
"eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode",
"eventStatus": "https://schema.org/EventScheduled",
"location": {
"@type": "VirtualLocation",
"url": "https://example.com/live"
},
"offers": {
"@type": "Offer",
"price": 0,
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"url": "https://example.com/events/astro-live-webinar/"
},
"organizer": {
"@type": "Organization",
"name": "Example GmbH",
"url": "https://example.com"
}
}
price={0} describes a free event and still produces an offer.
Hybrid event
attendanceMode="Mixed" needs both the venue and onlineUrl, and outputs both locations.
This example also shows a rescheduled event whose tickets are sold on another site:
<EventSchema
name="Example Conf 2027"
startDate="2027-03-11"
endDate="2027-03-12"
attendanceMode="Mixed"
status="Rescheduled"
locationName="Kulturbrauerei"
locationAddress={{
streetAddress: 'Schönhauser Allee 36',
addressLocality: 'Berlin',
postalCode: '10435',
addressCountry: 'DE',
}}
onlineUrl="https://example.com/conf/stream"
url="https://tickets.example.org/conf-2027"
price="249.00"
priceCurrency="EUR"
availability="PreOrder"
/>
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Example Conf 2027",
"startDate": "2027-03-11",
"endDate": "2027-03-12",
"url": "https://tickets.example.org/conf-2027",
"eventAttendanceMode": "https://schema.org/MixedEventAttendanceMode",
"eventStatus": "https://schema.org/EventRescheduled",
"location": [
{
"@type": "Place",
"name": "Kulturbrauerei",
"address": {
"@type": "PostalAddress",
"streetAddress": "Schönhauser Allee 36",
"addressLocality": "Berlin",
"postalCode": "10435",
"addressCountry": "DE"
}
},
{
"@type": "VirtualLocation",
"url": "https://example.com/conf/stream"
}
],
"offers": {
"@type": "Offer",
"price": "249.00",
"priceCurrency": "EUR",
"availability": "https://schema.org/PreOrder",
"url": "https://tickets.example.org/conf-2027"
}
}
Props
| Prop | Type | Required | Default / fallback | Description |
|---|---|---|---|---|
id |
string |
No | – | Output as the event’s @id, so other nodes can reference it |
name |
string |
Yes | – | Event name |
startDate |
string | Date |
Yes | – | Start date or date-time, ISO 8601 |
endDate |
string | Date |
No (recommended) | – | End date or date-time; not before startDate |
description |
string |
No (recommended) | – | Event description |
imageUrl |
string | string[] (URL or /path) |
No (recommended) | – | Event image(s), output as an array |
url |
string (absolute URL) |
No (recommended) | – | Event page or ticket shop; also the offer URL |
attendanceMode |
'Offline' | 'Online' | 'Mixed' |
No | 'Offline' |
Output as eventAttendanceMode |
status |
'Scheduled' | 'Cancelled' | 'Postponed' | 'Rescheduled' |
No | 'Scheduled' |
Output as eventStatus |
locationName |
string |
Offline / Mixed | – | Venue name |
locationAddress |
PostalAddress |
Offline / Mixed | – | { streetAddress, addressLocality, addressRegion?, postalCode, addressCountry } |
onlineUrl |
string (absolute URL) |
Online / Mixed | – | Stream or event platform URL, output as VirtualLocation |
price |
number | string |
No (recommended) | – | Ticket price; 0 for free events; a string must be numeric like '249.00' |
priceCurrency |
string (ISO 4217) |
No (recommended) | – | Currency, e.g. 'EUR' |
availability |
'InStock' | 'OutOfStock' | 'PreOrder' | 'OnlineOnly' |
No | 'InStock' |
Ticket availability; needs price |
organizer |
{ name: string; url?: string; id?: string } |
No (recommended) | – | Organizer, output as Organization; url absolute; id output as @id |
performer |
{ name: string; url?: string; id?: string } |
No | – | Performer or speaker, output as Person; url absolute; id output as @id |
superEvent |
{ type?, id?, name?, headline?, url? } |
No | – | Reference by id or url; type is free text, default 'Event' |
subEvent |
{ type?, id?, name?, headline?, url?, position? }[] |
No | – | Reference by id or url; type is free text, default 'Event' |
changefreq, priority |
sitemap hints | No | – | See Meta tags and sitemap hints |
“URL or /path” means an absolute http(s) URL or a root-relative path. In
locationAddress, all fields except addressRegion are required. organizer, performer
and locationAddress allow no other fields.
Rules
Violations fail the build (see Validation):
-
The location follows
attendanceMode:attendanceModelocationName+locationAddressonlineUrllocationoutputOffline(default)required not allowed PlaceOnlinenot allowed required VirtualLocationMixedrequired required [Place, VirtualLocation] -
priceandpriceCurrencyare set together or not at all.availabilityneedsprice. -
endDatemust not be beforestartDate. Dates are ISO 8601 orDateobjects. -
url,onlineUrl,organizer.urlandperformer.urlmust be absolutehttp(s)URLs.
The component uses no integration defaults apart from siteUrl (for the offer URL).
Recommended fields (endDate, description, image, url, offers, organizer) are
reported after the build when missing, unless warnOnMissingRecommended is off.