@growth-labs/cms 0.8.24 → 0.8.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +23 -0
  2. package/dist/engine/published-content.d.ts +4 -0
  3. package/dist/engine/published-content.d.ts.map +1 -1
  4. package/dist/engine/published-content.js +61 -19
  5. package/dist/engine/published-content.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/integration/options.d.ts +226 -13
  11. package/dist/integration/options.d.ts.map +1 -1
  12. package/dist/integration/options.js +17 -2
  13. package/dist/integration/options.js.map +1 -1
  14. package/dist/providers/types.d.ts +17 -1
  15. package/dist/providers/types.d.ts.map +1 -1
  16. package/dist/providers/types.js.map +1 -1
  17. package/dist/routes/content-insights.d.ts +4 -0
  18. package/dist/routes/content-insights.d.ts.map +1 -1
  19. package/dist/routes/content-insights.js +104 -0
  20. package/dist/routes/content-insights.js.map +1 -1
  21. package/dist/routes/surveys.d.ts.map +1 -1
  22. package/dist/routes/surveys.js +80 -4
  23. package/dist/routes/surveys.js.map +1 -1
  24. package/dist/schema/insights-ingest.d.ts +64 -64
  25. package/dist/schema/migrations.d.ts.map +1 -1
  26. package/dist/schema/migrations.js +7 -4
  27. package/dist/schema/migrations.js.map +1 -1
  28. package/dist/surveys/auto-label.d.ts +31 -4
  29. package/dist/surveys/auto-label.d.ts.map +1 -1
  30. package/dist/surveys/auto-label.js +160 -29
  31. package/dist/surveys/auto-label.js.map +1 -1
  32. package/dist/surveys/readout.d.ts +69 -0
  33. package/dist/surveys/readout.d.ts.map +1 -0
  34. package/dist/surveys/readout.js +157 -0
  35. package/dist/surveys/readout.js.map +1 -0
  36. package/dist/surveys/schema.d.ts +156 -0
  37. package/dist/surveys/schema.d.ts.map +1 -1
  38. package/dist/surveys/schema.js +50 -1
  39. package/dist/surveys/schema.js.map +1 -1
  40. package/dist/ui/api/content/insights-inputs.d.ts.map +1 -1
  41. package/dist/ui/api/content/insights-inputs.js +11 -1
  42. package/dist/ui/api/content/insights-inputs.js.map +1 -1
  43. package/dist/ui/client/mount.d.ts.map +1 -1
  44. package/dist/ui/client/mount.js +1 -0
  45. package/dist/ui/client/mount.js.map +1 -1
  46. package/dist/ui/screens/PodcastListeningScreen.d.ts.map +1 -1
  47. package/dist/ui/screens/PodcastListeningScreen.js +16 -2
  48. package/dist/ui/screens/PodcastListeningScreen.js.map +1 -1
  49. package/dist/ui/screens/SurveyResponsesScreen.d.ts +36 -3
  50. package/dist/ui/screens/SurveyResponsesScreen.d.ts.map +1 -1
  51. package/dist/ui/screens/SurveyResponsesScreen.js +271 -107
  52. package/dist/ui/screens/SurveyResponsesScreen.js.map +1 -1
  53. package/dist/ui/screens/podcast-listening-data.d.ts +1 -1
  54. package/dist/ui/screens/podcast-listening-data.d.ts.map +1 -1
  55. package/dist/ui/screens/podcast-listening-data.js +26 -1
  56. package/dist/ui/screens/podcast-listening-data.js.map +1 -1
  57. package/dist/ui/screens/registry.d.ts +3 -1
  58. package/dist/ui/screens/registry.d.ts.map +1 -1
  59. package/dist/ui/screens/registry.js +4 -2
  60. package/dist/ui/screens/registry.js.map +1 -1
  61. package/dist/ui/styles/broadsheet.css +136 -0
  62. package/package.json +2 -3
  63. package/src/engine/published-content.ts +86 -19
  64. package/src/index.ts +1 -0
  65. package/src/integration/options.ts +21 -1
  66. package/src/providers/types.ts +16 -1
  67. package/src/routes/content-insights.ts +104 -0
  68. package/src/routes/surveys.ts +106 -4
  69. package/src/schema/migrations.ts +7 -4
  70. package/src/surveys/auto-label.ts +204 -33
  71. package/src/surveys/readout.ts +243 -0
  72. package/src/surveys/schema.ts +59 -1
  73. package/src/ui/api/content/insights-inputs.ts +8 -1
  74. package/src/ui/client/mount.tsx +1 -0
  75. package/src/ui/screens/PodcastListeningScreen.tsx +30 -0
  76. package/src/ui/screens/SurveyResponsesScreen.tsx +964 -305
  77. package/src/ui/screens/podcast-listening-data.ts +33 -1
  78. package/src/ui/screens/registry.tsx +6 -2
  79. package/src/ui/styles/broadsheet.css +136 -0
@@ -42,6 +42,7 @@ export async function mount(elementId = 'masthead-root') {
42
42
  primaryTopic: config.primaryTopic,
43
43
  contentMetadataSelects: config.contentMetadataSelects,
44
44
  surveyId: config.surveyResults?.surveyId,
45
+ surveys: config.surveyResults?.surveys,
45
46
  })
46
47
  createRoot(el).render(<CmsApp initial={initial} screens={screens} boot={boot} />)
47
48
  }
@@ -165,6 +165,14 @@ function PodcastListeningBody({ data }: { data: PodcastListening }) {
165
165
 
166
166
  return (
167
167
  <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--gap)' }}>
168
+ <div className="page-sub">
169
+ {data.listeningStartedAt
170
+ ? `Listening time has been recorded since ${new Date(data.listeningStartedAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric', timeZone: 'UTC' })} (UTC). `
171
+ : 'The start of listening-time coverage is unavailable. '}
172
+ Plays cover the selected range. Listening time counts content played on the website,
173
+ including at faster speeds. Listening inside podcast apps cannot be measured here; a feed
174
+ download is not a measured listen. Averages use only sessions with recorded listening time.
175
+ </div>
168
176
  {!listeningMeasured && <ListeningPendingBanner />}
169
177
  <PodcastTotalsCards data={data} />
170
178
  <PodcastEpisodeTable episodes={data.episodes} />
@@ -211,6 +219,17 @@ function PodcastTotalsCards({ data }: { data: PodcastListening }) {
211
219
  value: t.totalListeningSeconds === null ? '—' : formatDuration(t.totalListeningSeconds),
212
220
  note: t.totalListeningSeconds === null ? 'not reported yet' : 'total, all episodes',
213
221
  },
222
+ {
223
+ label: 'Avg / measured session',
224
+ value:
225
+ t.avgListeningSecondsPerListener == null
226
+ ? '—'
227
+ : formatDuration(t.avgListeningSecondsPerListener),
228
+ note:
229
+ t.measuredListeners == null
230
+ ? 'measurement unavailable'
231
+ : `${formatNumber(t.measuredListeners)} measured sessions`,
232
+ },
214
233
  ]
215
234
  return (
216
235
  <div className="grid-stats">
@@ -258,6 +277,7 @@ const COLUMNS: ColumnDef[] = [
258
277
  { key: 'completes', label: 'Done', align: 'right' },
259
278
  { key: 'completionRate', label: 'Rate', align: 'right' },
260
279
  { key: 'totalListeningSeconds', label: 'Listening', align: 'right' },
280
+ { key: 'avgListeningSecondsPerListener', label: 'Avg / measured session', align: 'right' },
261
281
  ]
262
282
 
263
283
  export function PodcastEpisodeTable({
@@ -402,6 +422,16 @@ export function PodcastEpisodeTable({
402
422
  formatDuration(episode.totalListeningSeconds)
403
423
  )}
404
424
  </td>
425
+ <td style={{ paddingRight: 18 }}>
426
+ {episode.avgListeningSecondsPerListener === null
427
+ ? '—'
428
+ : formatDuration(episode.avgListeningSecondsPerListener)}
429
+ {episode.measuredListeners != null && (
430
+ <div className="kicker">
431
+ {formatNumber(episode.measuredListeners)} measured sessions
432
+ </div>
433
+ )}
434
+ </td>
405
435
  <td style={{ paddingRight: 18 }}>
406
436
  <DropoffBars episode={episode} />
407
437
  </td>