Skip to content

Support profiles custom events filters#482

Open
Blaumaus wants to merge 1 commit intomainfrom
profiles-custom-ev-filters
Open

Support profiles custom events filters#482
Blaumaus wants to merge 1 commit intomainfrom
profiles-custom-ev-filters

Conversation

@Blaumaus
Copy link
Member

@Blaumaus Blaumaus commented Mar 7, 2026

Changes

If applicable, please describe what changes were made in this pull request.

Community Edition support

  • Your feature is implemented for the Swetrix Community Edition
  • This PR only updates the Cloud (Enterprise) Edition code (e.g. Paddle webhooks, blog, payouts, etc.)

Database migrations

  • Clickhouse / MySQL migrations added for this PR
  • No table schemas changed in this PR

Documentation

  • You have updated the documentation according to your PR
  • This PR did not change any publicly documented endpoints

Summary by CodeRabbit

  • New Features

    • Custom event filtering is now fully propagated across analytics endpoints for consistent behavior.
  • Bug Fixes

    • Analytics profiles now correctly include custom event data when custom event filters are applied, previously omitted.

@Blaumaus Blaumaus self-assigned this Mar 7, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

The changes extend analytics filtering across cloud and community backends by introducing a customEVFilterApplied flag that is extracted from filter queries and propagated through controller and service methods. This flag controls conditional inclusion of custom event data when aggregating profiles, sessions, and time-bucketed analytics data.

Changes

Cohort / File(s) Summary
Cloud Analytics Controller
backend/apps/cloud/src/analytics/analytics.controller.ts
Destructuring updated to capture customEVFilterApplied from getFiltersQuery. Flag is passed as additional argument to groupByTimeBucket, getProfilesList, and getSessionsList methods.
Cloud Analytics Service
backend/apps/cloud/src/analytics/analytics.service.ts
Added optional customEVFilterApplied parameter to getProfilesList signature. Introduces conditional CTE construction for all_profile_data: unifies analytics and customEV data when flag is true, otherwise uses analytics-only approach.
Community Analytics Controller
backend/apps/community/src/analytics/analytics.controller.ts
Destructuring updated to capture customEVFilterApplied from getFiltersQuery. Flag is threaded as additional argument to groupByTimeBucket, getProfilesList, and getSessionsList method calls.
Community Analytics Service
backend/apps/community/src/analytics/analytics.service.ts
Added optional customEVFilterApplied parameter to getProfilesList signature. Implements conditional SQL logic: when true, builds unified CTE combining analytics and customEV rows; when false, preserves prior inline behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A flag hops through the filter chain,
Linking clouds and realms of grain,
Custom events and views unite,
When customEV shines its light! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Support profiles custom events filters' clearly describes the main change: adding support for custom event filtering in profile endpoints across both cloud and community editions.
Description check ✅ Passed The PR description follows the required template and includes completed checkboxes indicating the feature is implemented for Community Edition, no schema changes, and no endpoint documentation changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch profiles-custom-ev-filters

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/apps/cloud/src/analytics/analytics.service.ts`:
- Around line 4954-4998: The analytics arm inside allProfileDataCTE is missing
${filtersQuery}, causing pageviews/sessions to be unfiltered while events are
filtered; update the analytics SELECT (the first UNION ALL branch in
allProfileDataCTE) to include the same ${filtersQuery} (and keep
${profileTypeFilter} and pid checks) so that analytics rows are restricted to
the same event-level filters used for customEV, ensuring eventsCount and
pageview/session totals represent the same filtered slice.
- Around line 4954-5035: The all_profile_data CTE currently omits the requested
time window, so update the CTE construction (both branches where
customEVFilterApplied is true/false and inside the analytics SELECT, the
customEV SELECT, and the IN subquery) to constrain rows to the groupFrom/groupTo
range by adding the created time filter (use groupFrom/groupTo parameters into
the ClickHouse query placeholders, e.g., created >= {groupFrom} AND created <=
{groupTo} or an equivalent BETWEEN expression). Ensure you add this filter
alongside existing WHERE clauses in the code that builds allProfileDataCTE
(references: allProfileDataCTE variable, groupFrom, groupTo,
customEVFilterApplied, filtersQuery, profileTypeFilter) so
sessionsCount/pageviewsCount/eventsCount/firstSeen/lastSeen reflect the selected
period.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2e5369c8-9efd-46b5-8066-30fc93d5fc37

📥 Commits

Reviewing files that changed from the base of the PR and between 903c955 and 851f542.

📒 Files selected for processing (4)
  • backend/apps/cloud/src/analytics/analytics.controller.ts
  • backend/apps/cloud/src/analytics/analytics.service.ts
  • backend/apps/community/src/analytics/analytics.controller.ts
  • backend/apps/community/src/analytics/analytics.service.ts

Comment on lines +4954 to +4998
if (customEVFilterApplied) {
allProfileDataCTE = `
all_profile_data AS (
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
1 AS isPageview,
0 AS isEvent
FROM analytics
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
AND profileId IN (
SELECT DISTINCT profileId
FROM customEV
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
)
UNION ALL
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
0 AS isPageview,
1 AS isEvent
FROM customEV
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
)`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid mixing filtered event totals with unfiltered analytics totals.

In this branch, ${filtersQuery} is applied to the customEV arm but not to the analytics arm. Once a profile matches one filtered event, the row starts accumulating unfiltered pageviews/sessions while eventsCount stays filtered, so the profile totals no longer describe the same slice of data.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/apps/cloud/src/analytics/analytics.service.ts` around lines 4954 -
4998, The analytics arm inside allProfileDataCTE is missing ${filtersQuery},
causing pageviews/sessions to be unfiltered while events are filtered; update
the analytics SELECT (the first UNION ALL branch in allProfileDataCTE) to
include the same ${filtersQuery} (and keep ${profileTypeFilter} and pid checks)
so that analytics rows are restricted to the same event-level filters used for
customEV, ensuring eventsCount and pageview/session totals represent the same
filtered slice.

Comment on lines +4954 to +5035
if (customEVFilterApplied) {
allProfileDataCTE = `
all_profile_data AS (
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
1 AS isPageview,
0 AS isEvent
FROM analytics
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
AND profileId IN (
SELECT DISTINCT profileId
FROM customEV
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
)
UNION ALL
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
0 AS isPageview,
1 AS isEvent
FROM customEV
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
)`
} else {
allProfileDataCTE = `
all_profile_data AS (
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
1 AS isPageview,
0 AS isEvent
FROM analytics
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
UNION ALL
SELECT
profileId,
psid,
cc,
os,
br,
dv,
created,
0 AS isPageview,
1 AS isEvent
FROM customEV
WHERE pid = {pid:FixedString(12)}
AND profileId IS NOT NULL
AND profileId != ''
${profileTypeFilter}
${filtersQuery}
)`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Constrain all_profile_data to the requested time window.

groupFrom/groupTo are already passed into this method, but none of the new CTE branches use them. That makes /analytics/profiles aggregate all-time rows, so sessionsCount, pageviewsCount, eventsCount, firstSeen, and lastSeen ignore the selected period.

🐛 Proposed fix
         all_profile_data AS (
           SELECT
             profileId,
@@
           FROM analytics
           WHERE pid = {pid:FixedString(12)}
             AND profileId IS NOT NULL
             AND profileId != ''
             ${profileTypeFilter}
+            AND created BETWEEN {groupFrom:String} AND {groupTo:String}
             AND profileId IN (
               SELECT DISTINCT profileId
               FROM customEV
               WHERE pid = {pid:FixedString(12)}
                 AND profileId IS NOT NULL
                 AND profileId != ''
                 ${profileTypeFilter}
+                AND created BETWEEN {groupFrom:String} AND {groupTo:String}
                 ${filtersQuery}
             )
@@
           FROM customEV
           WHERE pid = {pid:FixedString(12)}
             AND profileId IS NOT NULL
             AND profileId != ''
             ${profileTypeFilter}
+            AND created BETWEEN {groupFrom:String} AND {groupTo:String}
             ${filtersQuery}
         )`
@@
         all_profile_data AS (
           SELECT
             profileId,
@@
           FROM analytics
           WHERE pid = {pid:FixedString(12)}
             AND profileId IS NOT NULL
             AND profileId != ''
             ${profileTypeFilter}
+            AND created BETWEEN {groupFrom:String} AND {groupTo:String}
             ${filtersQuery}
@@
           FROM customEV
           WHERE pid = {pid:FixedString(12)}
             AND profileId IS NOT NULL
             AND profileId != ''
             ${profileTypeFilter}
+            AND created BETWEEN {groupFrom:String} AND {groupTo:String}
             ${filtersQuery}
         )`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/apps/cloud/src/analytics/analytics.service.ts` around lines 4954 -
5035, The all_profile_data CTE currently omits the requested time window, so
update the CTE construction (both branches where customEVFilterApplied is
true/false and inside the analytics SELECT, the customEV SELECT, and the IN
subquery) to constrain rows to the groupFrom/groupTo range by adding the created
time filter (use groupFrom/groupTo parameters into the ClickHouse query
placeholders, e.g., created >= {groupFrom} AND created <= {groupTo} or an
equivalent BETWEEN expression). Ensure you add this filter alongside existing
WHERE clauses in the code that builds allProfileDataCTE (references:
allProfileDataCTE variable, groupFrom, groupTo, customEVFilterApplied,
filtersQuery, profileTypeFilter) so
sessionsCount/pageviewsCount/eventsCount/firstSeen/lastSeen reflect the selected
period.

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.

1 participant