Skip to content

feat: unified view logging – track article views on post open - #6380

Merged
rebelchris merged 1 commit into
mainfrom
feat/unified-post-view-logging
Jul 28, 2026
Merged

feat: unified view logging – track article views on post open#6380
rebelchris merged 1 commit into
mainfrom
feat/unified-post-view-logging

Conversation

@rebelchris

@rebelchris rebelchris commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Before: opening an article's post page or modal did not count toward reading streaks/reading days — a view was only recorded server-side when the reader clicked "Read article" (the api.daily.dev/r/:postId link). Every other post type (freeform, welcome, share, collection, brief, digest, poll, social:twitter) already logged a view as soon as the page/modal opened.
  • After: opening an article's post page or modal now logs a view too, via the same viewPost mutation (useTrackPostView / useViewPost) every other post type already uses. PostContent.tsx and PostFocusCard.tsx (the layout_v2 focus card) now call useTrackPostView({ post }) unconditionally instead of gating on isVideoType / a hardcoded viewTrackedPostTypes list, which is now dead code and removed.
  • This pairs with the companion backend PR feat: unified view logging – count article views on post open daily-api#4026: the backend does a server-side week-window dedup between the "opened post" view and the "clicked read article" view, so this change does not double-count reading streaks/reading days for millions of developers reading articles. No deploy-order constraint between the two PRs.
  • No feature flag — this ships directly to everyone.

Changes

  • packages/shared/src/components/post/PostContent.tsx: useTrackPostView({ post, shouldTrack: isVideoType })useTrackPostView({ post }). isVideoType is still used elsewhere in the file (layout/metadata), so it's untouched otherwise.
  • packages/shared/src/components/post/focus/PostFocusCard.tsx: same change, plus deletion of the now-unused viewTrackedPostTypes array. isVideoPost and PostType are still used elsewhere in the file, so their imports are unchanged.
  • Test updates (webapp PostPage.tsx spec, shared Feed.spec.tsx): added/adjusted viewPost mutation mocks now that opening an article's post page/modal fires that mutation. Added an explicit "should log post view on mount" test for articles in PostPage.tsx, mirroring the existing collection-type test. Also hardened two Feed.spec.tsx tests that were silently inheriting a leftover pmid router-mock query from a preceding test (a pre-existing test-isolation gap that only started mattering once articles began tracking views too).

Test plan

  • node ./scripts/typecheck-strict-changed.js — passes on all changed files.
  • NODE_ENV=test pnpm --filter shared test — 2001/2004 pass. The 3 failures (src/lib/numberFormat.spec.ts, locale-formatting comma-vs-period) are pre-existing on origin/main and unrelated to this change (verified via git stash).
  • NODE_ENV=test pnpm --filter webapp test — 298/298 pass.
  • eslint on all changed files — clean.

🤖 Generated with Claude Code

Preview domain

https://feat-unified-post-view-logging.preview.app.daily.dev

Articles previously only counted a view (for reading streaks/reading
days) when the user clicked "Read article"; every other post type
already logged a view on page/modal open. Track it unconditionally in
PostContent and PostFocusCard so opening an article's post page or
modal counts the same way, matching a companion daily-api change that
dedups against the existing read-article click.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Jul 27, 2026 6:00pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Jul 27, 2026 6:00pm

Request Review

@rebelchris rebelchris left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline commentary for reviewers: where the actual behavior change lives, and which parts are just test fallout.

};

useTrackPostView({ post, shouldTrack: isVideoType });
useTrackPostView({ post });

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one-liner is the actual behavior change of the PR: PostContent renders article (and video/liveRoom) posts, and the shouldTrack: isVideoType gate meant articles never sent viewPost on open — they only got a view server-side when the user clicked "Read article" (which routes through api.daily.dev/r/:postId).

Now opening the page or modal counts, same as freeform/welcome/share/collection/poll/brief/digest already do. The click-through path still exists unchanged; the backend dedups the two within a one-week window per (user, post) — see dailydotdev/daily-api#4026.

post,
shouldTrack: isVideoPost(post) || viewTrackedPostTypes.includes(post.type),
});
useTrackPostView({ post });

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same change for the layout-v2 focus card, which duplicated the article exclusion via its own viewTrackedPostTypes allowlist (deleted above — it's dead once tracking is unconditional). isVideoPost/PostType imports stay because both are still used elsewhere in this file.

await waitFor(() => expect(viewPostCallCount).toBe(3));
});

it('should report irrelevant tags', async () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer note: this router-mock reset (and the one in the next test) fixes a pre-existing test-isolation gap rather than anything introduced here. The two preceding tests set a pmid router query via mockImplementation, which jest.clearAllMocks() doesn't reset, so these tests were silently rendering with a leftover pmid and auto-opening the post modal all along. That was harmless while articles didn't track views; once they do, the modal fires an unmocked viewPost and nock fails the test — which is how the latent bleed-over surfaced.

},
result: () => ({ data: { _: true } }),
},
// Opening any post (including articles) now logs a view on mount; tests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default catch-all mock so the ~40 existing article-page tests don't each need to care about the new on-mount mutation; the new should log post view on mount test below asserts the behavior explicitly. Registered last so any test-supplied mock for the same request takes precedence.

@rebelchris
rebelchris requested review from capJavert and idoshamun and removed request for idoshamun July 28, 2026 08:31
@rebelchris
rebelchris merged commit 97e82f7 into main Jul 28, 2026
18 checks passed
@rebelchris
rebelchris deleted the feat/unified-post-view-logging branch July 28, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants