🎨 Made pages clickable in analytics Top content#28707
Conversation
ref https://linear.app/tryghost/issue/NY-1366 - previously only post rows in the Web and Growth tab Top content lists were clickable (they linked to the per-post analytics view); page rows and the homepage row had no link, so there was no quick way to jump from analytics to the live page - the stats services now resolve an absolute frontend URL for posts and pages via the URL service (and fall back to the site URL for the homepage attribution row), exposing it as a new `url` field - the Web and Growth tab tables make those rows clickable: posts still navigate to the internal analytics view, while pages and the homepage open the live frontend URL in a new tab
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx build @tryghost/comments-ui |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/announcement-bar |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/activitypub |
✅ Succeeded | 1s | View ↗ |
nx build @tryghost/signup-form |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/admin-toolbar |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/portal |
✅ Succeeded | <1s | View ↗ |
nx build @tryghost/sodo-search |
✅ Succeeded | <1s | View ↗ |
nx run @tryghost/admin-x-settings:test:acceptance |
✅ Succeeded | 9m 58s | View ↗ |
Additional runs (13) |
✅ Succeeded | ... | View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-06-22 12:59:01 UTC
ref https://linear.app/tryghost/issue/NY-1366 - the prior commit always set `url` on the row (potentially `undefined`), which broke `assert.deepEqual` against fixtures that don't list `url` - only spread `url` into the response when it actually resolved, so the response shape stays minimal and existing fixtures keep working
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #28707 +/- ##
==========================================
- Coverage 73.76% 73.73% -0.04%
==========================================
Files 1552 1552
Lines 134208 134309 +101
Branches 16108 16117 +9
==========================================
+ Hits 99004 99036 +32
- Misses 34225 34294 +69
Partials 979 979
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
E2E Tests FailedTo view the Playwright test report locally, run: REPORT_DIR=$(mktemp -d) && gh run download 27940032840 -n playwright-report -D "$REPORT_DIR" && npx playwright show-report "$REPORT_DIR" |

Summary
ref https://linear.app/tryghost/issue/NY-1366
Previously only post rows in the Web and Growth tab Top content lists were clickable — clicking a post navigates to its per-post analytics view. Page rows and the homepage row had no link, so there was no quick way to jump from analytics to the live page.
This PR makes those rows clickable. Posts still go to the internal analytics view; pages and the homepage open the live frontend URL in a new tab.
How it works
Server (
ghost/core/core/server/services/stats/)content-stats-service.js(Web tab) andposts-stats-service.js(Growth tab) now resolve an absolute frontend URL for posts and pages viaurlService.getUrlByResourceId(id, {absolute: true}). Result is exposed as a newurlfield on each row.attribution_type='url', path/) and the Web tab homepage row that doesn't match apostsresource, the URL is built fromurlUtils.urlFor('home', true).getResourceTitle()also retries the opposite trailing-slash form to catch pathnames recorded by Tinybird without a canonical slash.Client (
apps/stats/)getClickHandlerinurl-helpers.tsgained an optionalabsoluteUrlarg and prefers it over reconstructing from pathname when present.top-content.tsxand Growth tabgrowth.tsx: clickable gate relaxed — any row with a server-resolvedurlbecomes a link button.Notes / open questions
posts-stats-service.jsdoesn't run locally (pre-existingbeforeAll is not definedissue onmain).Test plan
postsrow remain non-clickable.pnpm --filter ghost test:single test/unit/server/services/stats/content.test.jsshould pass (25/25).