Background
PRs #263 and #267 introduced a pattern where the full page structure — section headings, row labels, and — placeholder values — renders synchronously on page load. Only the actual numbers fill in after the async GA4 fetch completes. This makes pages feel fast and gives users immediate context.
The main hub page (hubs/show.html.erb) and contributor page (contributors/show.html.erb) both use this pattern: their render_async_section blocks render a full skeleton partial as their placeholder.
Pages Still Using Bare Loading...
The following views still use a plain <div>Loading...</div> as the async placeholder, so the entire content area is blank until GA4 data arrives:
app/views/events/show.html.erb — used by all event pages: /events/view_item, /events/view_exhibit, /events/view_pss, /events/click_through, /events/view_api. Both the website-events and api-events async blocks show only Loading....
app/views/search_terms/show.html.erb — the website search terms and API search terms sections both show only Loading....
Work Needed
For each of these pages, apply the same pattern as the hub/contributor pages:
- Identify all the section headings, table structure, and row labels that are statically known (they don't depend on GA4 data).
- Extract a skeleton partial (or inline the skeleton in the
render_async_section block) that renders that structure with — placeholders using dash_or(nil).
- Replace the bare
<div>Loading...</div> placeholder with the skeleton render.
The events pages each have slightly different layouts (view_item shows a chart + table, click_through is table-only, etc.) so each will need a bespoke skeleton. The params[:id] branch in events/show.html.erb may be worth refactoring into per-event partials as part of this work.
Reference
Background
PRs #263 and #267 introduced a pattern where the full page structure — section headings, row labels, and
—placeholder values — renders synchronously on page load. Only the actual numbers fill in after the async GA4 fetch completes. This makes pages feel fast and gives users immediate context.The main hub page (
hubs/show.html.erb) and contributor page (contributors/show.html.erb) both use this pattern: theirrender_async_sectionblocks render a full skeleton partial as their placeholder.Pages Still Using Bare
Loading...The following views still use a plain
<div>Loading...</div>as the async placeholder, so the entire content area is blank until GA4 data arrives:app/views/events/show.html.erb— used by all event pages:/events/view_item,/events/view_exhibit,/events/view_pss,/events/click_through,/events/view_api. Both the website-events and api-events async blocks show onlyLoading....app/views/search_terms/show.html.erb— the website search terms and API search terms sections both show onlyLoading....Work Needed
For each of these pages, apply the same pattern as the hub/contributor pages:
render_async_sectionblock) that renders that structure with—placeholders usingdash_or(nil).<div>Loading...</div>placeholder with the skeleton render.The events pages each have slightly different layouts (view_item shows a chart + table, click_through is table-only, etc.) so each will need a bespoke skeleton. The
params[:id]branch inevents/show.html.erbmay be worth refactoring into per-event partials as part of this work.Reference
app/helpers/application_helper.rb—dash_orhelper