Skip to content

fix(views): stop over-counting weekly unique for repeat same-week views#7761

Open
ar2rsawseen wants to merge 5 commits into
masterfrom
test/views-weekly-unique-overcount
Open

fix(views): stop over-counting weekly unique for repeat same-week views#7761
ar2rsawseen wants to merge 5 commits into
masterfrom
test/views-weekly-unique-overcount

Conversation

@ar2rsawseen

@ar2rsawseen ar2rsawseen commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

Fixes a data-correctness bug in live view ingestion: when one device views the same view in two sessions within a single ISO week, the view-data weekly-unique bucket (d.w<week>.u) was recorded as 2 instead of 1.

Root cause

In recordMetrics (plugins/views/api/api.js), the weekly-unique gate built its comparison moment with new moment(lastViewTimestamp). lastViewTimestamp is a unix timestamp in seconds (the adjacent day/month/year gates compare it against timestamp - secInX), but moment(Number) treats the value as milliseconds — placing it in 1970. isoWeek() of that 1970 date is a tiny number that is almost always < weeklyISO, so the gate fired on every repeat view in the same week and re-incremented d.w<week>.u. Daily/monthly/yearly gates were unaffected (they use correct elapsed-seconds comparisons), which is why only weekly over-counted. Fix: use moment.unix().

Validation

  • Adds plugins/views/tests.js reproducing the scenario (same device, two same-week sessions). It failed on the first commit (d.w<week>.u came back as 2) and passes with the fix.
  • The assertion is timezone-robust and guards against a vacuous pass (requires a weekly-unique bucket to actually have been written and inspected).

Note: this corrects go-forward live counting only; already-stored weekly u values would need view-data regeneration to be corrected.

🤖 Generated with Claude Code

…views

Adds a views plugin test: one device views the same view in two sessions
within a single ISO week. The view-data weekly-unique bucket (d.w<week>.u)
must be 1, but live ingestion currently records 2 — it counts the same
user's repeat same-week view twice. Regeneration (EE drill) already
de-dupes correctly to 1; this test pins the live over-count in core where
it actually lives. Expected to FAIL until the live counting is fixed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 19, 2026 11:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a regression test intended to reproduce a data-correctness bug in the Views plugin: weekly-unique view counting (d.w<week>.u) is over-counted when the same device views the same view in two sessions within one ISO week.

Changes:

  • Add a new views ingestion test that sends two same-week sessions for one device/view and asserts weekly unique remains 1.
  • Compute a timezone-robust mid-week anchor timestamp for the previous ISO week.
  • Query app_viewsmeta and app_viewdata* rollups to validate weekly-unique buckets.

Comment thread plugins/views/tests.js
Comment thread plugins/views/tests.js
Comment thread plugins/views/tests.js
The weekly-unique gate in recordMetrics built its comparison moment with
new moment(lastViewTimestamp). lastViewTimestamp is a unix timestamp in
seconds (as the surrounding day/month/year gates treat it), but
moment(Number) interprets the value as milliseconds, placing it in 1970.
isoWeek() of that 1970 date is a tiny number that is almost always less
than the current weeklyISO, so the gate fired on every repeat view in the
same week and incremented d.w<week>.u again -> weekly unique counted 2 for
a single user. Daily/monthly/yearly gates were unaffected (they use
elapsed-seconds comparisons). Use moment.unix() so isoWeek() reflects the
real week.

Also harden plugins/views/tests.js to assert a weekly-unique bucket was
actually inspected (guards against a vacuous pass if weekly data stops
being written).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ar2rsawseen ar2rsawseen changed the title test(views): reproduce weekly-unique over-count for repeat same-week views fix(views): stop over-counting weekly unique for repeat same-week views Jun 19, 2026
ar2rsawseen and others added 2 commits June 19, 2026 15:52
…de events

Address review feedback:
- The test was named plugins/views/tests.js, which Node resolves in
  preference to the existing plugins/views/tests/ directory, shadowing the
  whole views suite (tests/index.js -> views.js). Move it to
  plugins/views/tests/weeklyUnique.js and require it from index.js so the
  existing suite keeps running.
- URL-encode the events JSON query param (encodeURIComponent) instead of
  concatenating raw JSON into the URL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the relocation: the new plugins/views/tests/weeklyUnique.js and
its require in tests/index.js were missing from the previous commit (which
only removed the shadowing plugins/views/tests.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ar2rsawseen

Copy link
Copy Markdown
Member Author

Thanks — addressed all three:

  1. Shadowing the existing views suite (good catch): plugins/views/tests.js resolved in preference to the existing plugins/views/tests/ directory, so it was hiding tests/index.js → views.js. Moved the new test to plugins/views/tests/weeklyUnique.js and added require('./weeklyUnique.js') to tests/index.js, and removed the top-level tests.js. The existing views suite now runs alongside it.

  2. URL-encoding the events param: now encodeURIComponent(JSON.stringify(...)).

  3. Failing spec blocking CI: the bugfix is included in this same PR (the moment.unix() fix in plugins/views/api/api.js), so the spec is expected to pass rather than fail — it fails only without the fix.

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.

3 participants