ETS data model (proposed, v0.1)

Proposed schema for the ETS27 site and its AI concierge, with the mapping back to WordPress, Whova and Eventbrite. Written 2026-10-13.

Companion files: ets-content-inventory.md (what exists today and the evidence) and ../prototype/data/ets.sample.json (a fixture that follows this model). Field names below are the fixture's field names unless a row says "production only".

1. Principles

  1. Per-edition facts, stable identities. A person is stable; their title, employer, bio and photo are not. Model Person once and Appearance per edition. The fixture flattens one edition (ETS26 stand-ins) and keeps the WordPress archive record under wp.
  2. One source of truth per field. Staff edit speakers, FAQ, venue and hotel in WordPress and the agenda in Whova. Anything the front end or concierge builds from them is a disposable snapshot, never a second editable copy (human-operable parity).
  3. Honest gaps. An unknown value is null with a status, never an invented value. Stand-in data carries placeholder: true and a basis.
  4. Readable ids. spk-greg-brown, ses-d2-1330-breakout-a, spn-itron, tkt-industry-phase1. A model can cite them, and a person can read them in a log.
  5. Plain text at the boundary. WPBakery shortcodes, HTML and entities are stripped when data enters the model.
  6. Time. ISO date, local 24-hour HH:MM, one event timezone (America/Chicago).
  7. One-hop answers. Every entity must answer its visitor questions (section 4) from its own fields or its direct references. If answering needs a two-hop join, add a field.
  8. Only announced data reaches visitors. Production adds a status (invited, confirmed, announced, withdrawn) to speakers, sessions and sponsors; the public front end and the concierge read announced only.

2. Entity map

Edition (event) 1--* Day 1--* Session *--* Appearance *--1 Person
     |                          |  |            (speaker or moderator)
     |                          |  +-- type: SessionType (format: keynote, panel ...)
     |                          +----- track: Track (theme, optional)
     |                          +----- room: Room (in Venue)   sponsor_ids: Sponsor
     +--1 Venue 1--* Hotel, Room
     +--* Sponsor *--1 SponsorTier
     +--* TicketClass
     +--* FAQ
     +--* Post (news, video)
     +--* Edition (past: archive, satellites)

Pages in the standard site map onto the same entities:

Standard page Entities
Home Edition, featured Person, SponsorTier and Sponsor strip, Post, TicketClass call to action
Lineup Person and Appearance
Agenda Day, Session, SessionType, Track
Hotel and venue Venue, Hotel, Room
Partners SponsorTier, Sponsor
Tickets TicketClass
FAQ FAQ
News, gallery Post, media
Past editions Edition (past), Post
Contact Edition.contact

3. Source of truth and sync

Entity Humans edit in Machine reads from Derived snapshot? Today
Edition (ETS27 facts) WordPress Event record (to be built) WordPress REST No Facts live only in a WPBakery block (Content Block 78148) and Eventbrite
Day, Session, SessionType Whova (ETS27 event) Whova public JSON, server-side job Yes ETS26 only; no ETS27 Whova event is referenced on the site
Track (theme) Whova tags, or a WordPress list Same Yes Not used; Whova "tracks" are formats
Person, Appearance Whova (current speakers, bios, photos); WordPress portfolio (archive, honors, featured) Both, merged by person key Yes Split across two systems
Venue, Hotel, Room WordPress Event record WordPress REST No Plain page copy
Sponsor, SponsorTier WordPress (structured Sponsor type, to be built) WordPress REST No Logo images only
TicketClass Eventbrite Eventbrite API with an organizer token, else hand-mirrored in the Event record Yes Visible only in the checkout panel
FAQ WordPress FAQ type (to be built) WordPress REST No Does not exist
Post WordPress posts WordPress REST No 5 video posts
Edition (past) WordPress WordPress REST No Separate microsites per year

Snapshot rule: the job that builds a snapshot validates it (referential integrity, no HTML, times valid), diffs it against the last good one, and refuses to publish a snapshot that drops more than a threshold of speakers or sessions.

4. Entities

Each entity has a field table and the visitor questions it must answer. "WP" is WordPress, "WV" is Whova, "EB" is Eventbrite. Required means required in the fixture.

4.1 Edition (event)

Field Type Req Notes and source
id string yes ets27; past editions ets26; satellites ets-chicago-2024
kind flagship or satellite editions ets@events one-day events are satellites
name, short_name string yes "Energy Thought Summit 2027", "ETS27"
year, edition_number int yes edition_number = year - 2013 (ETS23 was the 10th, ETS26 the 13th, ETS27 the 14th)
theme, tagline, hashtag string yes "Free Your Mind", "Free Your Mind. Shape the Future.", "#LoveYourEnergy" (EB copy)
description string yes Organizer copy from EB
status enum yes announced for ETS27
start_date, end_date, timezone ISO date, IANA zone yes 2027-05-03 to 2027-05-06, America/Chicago (EB JSON-LD, WP hero)
day_count_calendar, published_hours int, string no 4; "08:00-17:30" (EB)
city, region, country string yes Austin, TX, US
attendance_mode enum no in_person
organizer object yes Zpryme
urls, contact, social objects yes Register link keeps the affiliate parameter. Contact form subjects are listed
confirmed object of booleans yes dates, city, theme, register_link, ticket_prices true; venue, hotel, lineup, agenda, sponsors false. The concierge reads this before answering
venue (editions) string or null no Past venues; ETS23 Hotel ZaZa, ETS25 and ETS26 Boeing
eventbrite_url, pages url, urls no Archive links

Visitor questions:

Question Answered by If missing
When is it? start_date, end_date, published_hours Never missing
Where is it? city, region; venue.name Say the venue is to be announced (confirmed.venue false)
What is ETS and what is the theme? theme, tagline, description n/a
How do I register? urls.register, tickets n/a
Is the lineup or agenda out yet? confirmed.lineup, confirmed.agenda Offer the ETS26 program as a reference, labeled as such
Has it been held before, and where? editions[] n/a
Who runs it, how do I contact them? organizer, contact n/a
How do I follow updates? social, newsletter n/a

4.2 Day

Field Type Req Notes and source
id, n, label d1, 1, "Day 1" yes
date, weekday ISO date, string yes WV agenda[].date, .day
start, end HH:MM yes Earliest start, latest end of the day's sessions
session_count int yes Derived
summary string no Editorial one-liner (placeholder in the fixture)

Four days for ETS27 (Mon May 3 to Thu May 6); the fourth is a half day as in ETS23, ETS24 and ETS26.

Question Answered by If missing
What is on Tuesday? Sessions with day = d2 Say the agenda is not announced
What time does each day start and finish? start, end n/a
Is there a half day, when does it end? d4.end n/a
What is the evening plan? Sessions of type reception that day "No evening event announced"
When are meals and breaks? Sessions of type meal, break n/a
What date is Day 3? date, weekday n/a
What is the shape of a typical day? summary n/a

4.3 SessionType and Track

Whova's eight "tracks" are formats. The model splits them: SessionType is the format, Track is an optional theme.

SessionType ids: registration, ceremony, keynote, ets_talk, fireside, panel, town_hall, breakout, workshop, short_doc, meal, break, reception, each with label, speaker_led, note. Mapping:

WV track type
Keynote, Panel, Fireside Chat, Town Hall, Breakout, Workshop, ETS Talk, Feature Short-Doc keynote, panel, fireside, town_hall, breakout, workshop, ets_talk, short_doc
(none) and title starts "Registration" registration
(none) and title contains "Reception" reception
(none) and title starts "Networking Break" break
(none) and title contains "Breakfast" or "Lunch" meal
(none) and title starts "Breakout" breakout
(none) and title is an opening, closing or event close ceremony

Track fields: id, label, color_hint. ETS26 had no thematic tracks. The fixture invents seven placeholders from recurring session themes (ai-digital, resilience-security, customer-affordability, policy-planning, grid-edge, load-growth, people-community) and flags them placeholder: true, basis: invented. For ETS27, decide whether themes come from Whova tags or a WordPress list.

Question Answered by If missing
What formats are there, what is a Town Hall? session_types[].label, note n/a
Show me all keynotes Sessions with type = keynote n/a
Which sessions are about AI, security, affordability? topics, track Fall back to title search
What are the themes? tracks[] Say themes are not announced
Which are the short formats? duration_min by type n/a
Which sessions run in parallel, how do I choose? Sessions with the same day and start and type = breakout n/a

4.4 Session

Field Type Req Notes and source
id string yes ses-d{day}-{HHMM}-{slug}
day, date d2, ISO date yes WV calendar_stime date
start, end, duration_min HH:MM, int yes WV start_time, end_time
title string yes WV name
type SessionType id yes Mapping in 4.3
track, topics[] Track ids no Derived in the fixture; WV tags is empty today
description string or null no WV desc (HTML, stripped). 9 of 68 in ETS26
speaker_ids[], moderator_ids[] Person ids yes WV speaker.Speakers, .Speaker, .Moderator
room string or null no WV place. 22 of 68 in ETS26
sponsor_ids[] Sponsor ids no WV sponsors is empty today; ETS26 sponsors were named in titles
placeholder, basis bool, enum yes See section 6
source object fixture whova_session_id, original_title, original_date, original_start, original_end, whova_track, original_place, original_sponsor_note
production only status, capacity, livestream_url, recording_url, updated_at
Question Answered by If missing
When is X, how long is it? date, start, end, duration_min n/a
Who is speaking at X, who moderates? speaker_ids, moderator_ids n/a
Where is X? room "Room to be announced"
What is X about? description, else title and topics Offer the title only
What else is on at the same time? Same day, overlapping start and end n/a
Which sessions is Y in? Person session_ids n/a
Who sponsors this session? sponsor_ids n/a
Can I add it to my calendar? date, start, end, event timezone n/a

4.5 Person and Appearance (fixture: speakers[])

Field Type Req Notes and source
id, slug spk-{slug}, string yes Slug from WP when a record exists; WP slug john-d-hewa-copy is corrected to janet-rehberg
name, first_name, last_name string yes WV; WP title.rendered (decode entities)
title, org string or null yes WV title, company; WP custom fields company-title, company-name (not in REST)
bio string or null no Fixture: leading sentences, at most 60 words. WV bio first, then WP [vc_column_text]
bio_source whova-ets26, wp-ets25, null no
photo, photo_source, photo_alt url, enum, string no WP featured_media source_url, else WV pic; generic Whova avatars omitted; alt text written (WP has none)
category keynote, speaker, moderator yes Derived: any keynote session, else moderator-only, else speaker
featured bool no WV highlight_speakers or WP featured term
organizer_team bool no True for Zpryme staff
honors[] objects no TLOY: {program, code, year} from the "TLOY yyyy" label on /ets25/
session_ids[] Session ids yes Derived reverse index
placeholder, confirmed_for_ets27, basis yes Section 6
wp object or null no id, slug, url, featured_media_id, categories, ets25_title, ets25_org
source object fixture whova_pid, edition
production only person_key, aliases[], status, links, edition_id

Person key and matching: key on normalized first last, with an alias table (Chima and Chimaobi Chijioke, Rudy D. and Rudy Garza, H.G. and H G Chissell). The ETS26 to ETS25 match used last name plus first initial, then a manual check: 35 of 147 matched (31 exact, 4 by name variant).

Question Answered by If missing
Who is X? title, org, bio Show title and org; no bio for 41 of 77 fixture speakers
Who is speaking this year? Speakers with status = announced Say the lineup is not announced; offer ETS26 as reference
When is X on? session_ids n/a
Who is from utility or company Y? org search n/a
Who are the keynotes, who is featured? category, featured n/a
Has X spoken before, any honors? wp, honors n/a
What does X look like, link to a profile? photo, photo_alt, slug Show the placeholder portrait
How do I nominate a speaker? Contact subject "Nominate Thought Leader" n/a

4.6 Venue, Hotel, Room

Field Type Req Notes and source
id, name, city, region, country yes ETS27: "TBD - Austin, TX"
address, phone, website string or null no WP /venue/ copy for past venues
status not_announced, announced yes
eventbrite_listing object no EB location name and street pin; unconfirmed
hotels[] objects no name, role (host, overflow), booking_url, deadline, shuttle, status
rooms[] objects production id, name, level, capacity; WV place is free text today
getting_there object no Transit, airport, parking, accessibility (placeholder in the fixture)
prior_venue object no ETS26 venue, hotels, evening venues, and a note about the Boeing/Westin split
placeholder, basis yes
Question Answered by If missing
Where is it? name, address "To be announced"
How do I get there? getting_there Sustainability Promise transit guidance (labeled partial)
Where do I stay? hotels[] "Hotel block not announced; ETS26 pattern described"
Is there a shuttle, parking, step-free access? hotels[].shuttle, getting_there Not published: say so and give the contact
Which room is session X in? Session room against rooms[] "Room to be announced"
Where are the receptions? reception sessions, room n/a
What was the last venue like? prior_venue n/a
Who do I contact about the venue? Edition contact n/a

4.7 SponsorTier and Sponsor

Field Type Req Notes and source
Tier id, label, display_order yes Platinum, Vanguard, Trident, Gold, Silver, Bronze; display_order, not rank, because the page does not state a hierarchy
Sponsor id, name, tier spn-{slug} yes Names from logo file names today
logo_url, url url or null yes, no WP media; links are empty today
name_confidence, note enum, string fixture high, medium, low
placeholder, confirmed_for_ets27, basis yes
production only description, roles[] (reception, lunch, sustainability), booth, session_ids, since

Tier benefits and prices are not published anywhere.

Question Answered by If missing
Who sponsors ETS? sponsors by tier Say the ETS27 partner list is not announced; offer ETS26 partners as reference
What are the tiers and what do they get? sponsor_tiers Benefits not published; point to the contact form
How do I sponsor? Contact subject "Sponsor", /partners/ form n/a
What does company X do? description, url Name and logo only
Who sponsored the reception or lunch? Session sponsor_ids n/a
Is X a sponsor this year? confirmed_for_ets27 n/a
Is there an exhibit area? Not published (ETS23 mentioned a limited number of tabletop booths) Say so

4.8 TicketClass

Field Type Req Notes and source
id, name, audience, phase tkt-industry-phase1, "Industry", industry or government_utility, 1 or 2 yes EB checkout panel
price_with_fees, eventbrite_fee, base_price_derived number yes Base is derived (price minus fee)
sales_start, sales_end, available_now date, date, bool yes
Parent: eventbrite_url, currency, as_of, verify_before_display, sale_status, refund_policy, prices_include_eventbrite_fees, not_published[] yes EB JSON-LD and ticket-information
Question Answered by If missing
How much is it? price_with_fees, base_price_derived n/a
Industry versus Government and Utility? audience Eligibility rules not published
When does the price go up? Phase 1 sales_end, phase 2 sales_start n/a
How do I buy? eventbrite_url n/a
Refunds, transfers? refund_policy (no refunds); transfers not published Say so
What is included? not_published Say so
Group, student, press or speaker rates, codes? not_published Say so and give the contact
Is it on sale or sold out? sale_status, available_now n/a

4.9 FAQ

Field Type Req Notes
id, category, question, answer yes Categories: basics, tickets, attending, travel, get-involved
placeholder, basis, grounding[], source_urls[] yes grounding says which real text backs the answer
owner_to_confirm, volatile, partial_placeholder no
production only related_ids[], last_verified, status

Starter set (8): when and where, theme, register and cost, who should attend, hotel, getting around, dress, speak sponsor or volunteer. Likely next: accessibility, parking, wifi, dietary needs, children, international visitors, recordings, refunds in detail, what is included.

Question topic the FAQ must cover Today
Dress code Placeholder
Hotel and room block Placeholder (ETS26 pattern)
Travel and local transport Partial (Sustainability Promise)
Who should attend Grounded in ETS23 and home copy
Refunds and transfers Refunds grounded (EB); transfers unknown
Accessibility, parking, wifi, dietary No source yet
Speaking, sponsoring, volunteering Grounded (contact form)
Recordings and photos No source yet

4.10 Post

Field Type Req Notes and source
id, wp_id, slug, title, date, url yes WP posts
kind video, article yes All five live posts are video
youtube_id, image_url string no Parsed from the iframe; WP featured_media
category, excerpt string or null no Category "News"; excerpts empty
Question Answered by If missing
What is the latest news? Posts by date Latest is 2024-09-24; say news is quiet
Show me videos from past events kind = video n/a
Who spoke at past editions? title only (for example Wozniak at ETS14) No transcript; needs YouTube captions or a written summary
Where can I watch recordings? youtube_id, social youtube n/a
What happened last year? editions[], archive pages n/a
Can I share this? url n/a

5. Concierge snapshot, component catalog and tools

The project brief puts a compact knowledge snapshot in a cached prompt prefix and has the concierge answer with one structured result, {say, ui}, where ui is a list of components from an allow-listed catalog that carry record ids. The renderer draws each component from the site's own data by id and drops unknown ids. This model is built for that: ids are readable and stable, and every record carries its placeholder and confirmed flags.

5.1 Lean snapshot (goes in the prefix)

Keep the prefix to the fields the model needs to choose and cite; the renderer reads the rest by id.

Entity Fields in the snapshot
Edition name, theme, start_date, end_date, city, region, confirmed, register URL, contact email
Venue name, status, hotel names, prior venue name
Day, Track id, date, weekday, start, end / id, label
Session id, day, start, end, type, track, title, speaker_ids, moderator_ids
Speaker id, name, title, org, category, featured
Sponsor id, name, tier
TicketClass id, name, phase, price_with_fees, sales_start, sales_end
FAQ id, question, answer

Measured on the fixture: about 31.6 KB compact JSON, roughly 8,000 tokens by a characters-divided-by-four estimate (ids tokenize heavily, so measure with the real tokenizer). That fits the brief's 6 to 10 thousand token budget. Bios, descriptions, photos, wp archive blocks and source blocks stay out of the prefix. A real ETS27 lineup of 100 to 150 speakers will push the prefix up; at that point switch the speaker block to search (5.3).

5.2 Component catalog

Names follow the brief's first cut. Props are the few the model controls; the right-hand column is what the renderer reads by id.

Component Model supplies Renderer reads
speaker_grid speaker_ids[] name, title, org, photo, photo_alt, category, featured
speaker_card speaker_id Grid fields plus bio, honors, session_ids, wp.url
session_list session_ids[], or a filter (day, type, track) start, end, title, type, track, room, speaker names
session_card session_id List fields plus description, moderators, sponsor names
agenda_day day Day fields and its sessions grouped by start; parallel breakouts side by side
venue_card optional section (hotels, getting_there, prior) name, address, status, hotels[], getting_there, prior_venue
sponsor_wall optional tier tier, name, logo_url, url
ticket_cta none tickets.tiers, eventbrite_url, as_of, refund_policy
text_block text, or faq_id FAQ question, answer; placeholder
choices follow-up strings none
link_out kind (register, page, post, archive), id URLs from the Edition, Post and Edition records

Entities the first cut does not yet cover: past editions and videos (edition_timeline, video_card) and FAQ as a first-class item (faq_item, or keep using text_block). The sample marker is renderer-owned: any component that draws a record with placeholder: true shows it, and the model cannot switch it off.

5.3 Tools (only if the snapshot outgrows the prefix)

Tool Arguments Returns
search_speakers q?, org?, category?, session_id?, featured? Speaker ids with the snapshot fields
list_sessions day?, type?, track?, speaker_id?, sponsor_id?, q?, at? Session ids, grouped by start time
get_speaker, get_session id Full record with resolved references
search_faq q FAQ items ranked

Everything else (event, venue, tickets, sponsors, days, tracks) is small enough to stay in the prefix. Every tool result keeps the placeholder and confirmed flags.

6. Placeholder and provenance conventions

7. Normalization rules

Area Rule
Text Strip tags, decode entities (Whova bios contain '), trim; unknown becomes null, never an empty string
Names Whova name is the display name; WP name is an alias; straight apostrophes
Title and org Whova for the current edition; WP values kept as ets25_title, ets25_org
Dates calendar_stime gives the date; start_time and end_time are already 24-hour local
ETS26 to ETS27 relabel Shift dates by +371 days (Monday Apr 27, 2026 to Monday May 3, 2027); replace "ETS26" with "ETS27" in titles; strip venue and sponsor suffixes from receptions and lunch; keep the original in source
Photos Prefer the current edition's upload; omit generic avatars; add alt text; resize through an image service
Bios Detail pages show the full bio; cards use the leading sentences up to 60 words
Sponsors Names from logo file names are provisional; record name_confidence and replace with structured data
Edition number year - 2013

8. About the fixture

prototype/data/ets.sample.json follows this model with the keys meta, provenance, event, editions, venue, agenda (days, tracks, session_types, sessions), speakers, sponsor_tiers, sponsors, tickets, faq, posts.

Block Count Basis
Speakers 77 (30 fully complete, 36 with a bio, 59 with a photo, 27 with a WordPress archive record) Real ETS26 speakers, stand-ins
Sessions 50 over 4 days ETS26 program relabeled to ETS27 dates; 44 copied, 6 adapted (reception, lunch and ETS26-branded titles)
Tracks 7 Invented placeholders
Sponsors 39 in 6 tiers ETS26 partners, stand-ins
Tickets 4 classes Real, read 2026-10-13, verify before display
FAQ 8 (5 grounded, 3 placeholder) Mixed
Posts 5 Real
Editions 5 flagships, 2 satellites Real

Choices that differ from the original ask:

Checks run: the file parses as UTF-8 JSON; no HTML or entities in any string; every session, speaker, sponsor and day reference resolves; all bios are at most 60 words; all 103 image URLs returned HTTP 200 on 2026-10-13.

Do not paste the whole file into a model prompt (about 200 KB). Build the lean snapshot in section 5.1 from it (about 31.6 KB, roughly 8,000 tokens) and let the renderer read full records by id.

9. Facts only Zpryme can supply

Venue and hotel for ETS27; whether the ETS27 Whova event exists and whether an official Whova API credential is available; an Eventbrite API token or a person who will keep the ticket table current; ticket inclusions and discount rules; sponsor tier benefits and the ETS27 partner list; which FAQ answers are right (dress, accessibility, parking, recordings); whether the ETS23 and ETS24 press logos may be reused.