fix(google_analytics): migrate page-opened trigger from deprecated UA…#20046
fix(google_analytics): migrate page-opened trigger from deprecated UA…#20046luancazarine merged 2 commits intomasterfrom
Conversation
… API to GA4 Data API
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
WalkthroughBumps the Google Analytics package version and migrates the "New Page Opened" source from Universal Analytics (GA3) to the GA4 Data API, updating public props, query shape, metrics, response parsing, and metadata/event emission. Changes
Sequence DiagramsequenceDiagram
participant Source as Page-Opened Source
participant GA4 as GA4 Data API
participant Emitter as Event Emitter
Source->>GA4: queryReportsGA4(propertyId, dateRanges, metrics)
activate GA4
GA4-->>Source: GA4 report response (rows / totals)
deactivate GA4
Source->>Source: parse response (rows[0].metricValues... or totals[0].metricValues...)
Source->>Source: extract pageViews (fallback "0") and parseInt
Source->>Source: compare current vs previous pageViews
alt pageViews > previousPageViews
Source->>Emitter: emit(event, report, meta)
activate Emitter
Emitter-->>Source: acknowledgment
deactivate Emitter
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@components/google_analytics/sources/page-opened/page-opened.mjs`:
- Line 84: The condition using parseInt lacks an explicit radix; update the
parseInt calls for pageViews and previousPageViews in the if condition (the line
comparing previousPageViews and pageViews) to specify a radix (e.g.,
parseInt(pageViews, 10) and parseInt(previousPageViews, 10)) so parsing is
deterministic; alternatively, replace both with Number(pageViews) and
Number(previousPageViews) if you prefer clearer numeric conversion.
- Around line 58-82: Remove trailing whitespace in the affected block where
propertyId, report, previousPageViews, and pageViews are defined (the lines
around the propertyId assignment, the analytics.queryReportsGA4 call, and the
pageViews fallback expression) and ensure the file ends with a single newline
character; run a quick linter/trim to strip trailing spaces and add the missing
EOF newline so CI passes.
components/google_analytics/sources/page-opened/page-opened.mjs
Outdated
Show resolved
Hide resolved
| || "0"; | ||
|
|
||
| if (!previousPageViews || pageViews > previousPageViews) { | ||
| if (!previousPageViews || parseInt(pageViews) > parseInt(previousPageViews)) { |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Specify radix for parseInt.
Best practice is to always pass the radix to parseInt to avoid ambiguity.
♻️ Proposed fix
- if (!previousPageViews || parseInt(pageViews) > parseInt(previousPageViews)) {
+ if (!previousPageViews || parseInt(pageViews, 10) > parseInt(previousPageViews, 10)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!previousPageViews || parseInt(pageViews) > parseInt(previousPageViews)) { | |
| if (!previousPageViews || parseInt(pageViews, 10) > parseInt(previousPageViews, 10)) { |
🤖 Prompt for AI Agents
In `@components/google_analytics/sources/page-opened/page-opened.mjs` at line 84,
The condition using parseInt lacks an explicit radix; update the parseInt calls
for pageViews and previousPageViews in the if condition (the line comparing
previousPageViews and pageViews) to specify a radix (e.g., parseInt(pageViews,
10) and parseInt(previousPageViews, 10)) so parsing is deterministic;
alternatively, replace both with Number(pageViews) and Number(previousPageViews)
if you prefer clearer numeric conversion.
luancazarine
left a comment
There was a problem hiding this comment.
Hi @maycon-pipedream, please fix the lint errors
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.
In `@components/google_analytics/sources/page-opened/page-opened.mjs`:
- Around line 80-82: The fallback using report?.totals is dead because the
runReport request doesn't include metricAggregations; update the runReport
request construction (the object passed to analyticsDataClient.runReport) to
include metricAggregations: ["TOTAL"] so report.totals will be populated, and
then keep the pageViews computation (report?.rows?.. || report?.totals?.. ||
"0") as-is; alternatively, if you prefer removing dead code, delete the
report?.totals fallback from the pageViews assignment that reads from report to
rely solely on report?.rows and "0".
| const pageViews = report?.rows?.[0]?.metricValues?.[0]?.value | ||
| || report?.totals?.[0]?.metricValues?.[0]?.value | ||
| || "0"; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the actual code file to see the request construction
cat -n components/google_analytics/sources/page-opened/page-opened.mjs | sed -n '60,85p'Repository: PipedreamHQ/pipedream
Length of output: 921
🌐 Web query:
GA4 Data API runReport metricAggregations totals documentation
💡 Result:
To request totals (and other metric aggregations) in the GA4 Google Analytics Data API runReport response, you must set the metricAggregations field on the request.
Request (RunReportRequest)
Include one or more MetricAggregation enums in metricAggregations, e.g. TOTAL (sum), MINIMUM, MAXIMUM, COUNT. When you do this, the API notes that aggregated values can appear in rows whose dimensionValues are set to RESERVED_(MetricAggregation) (for example, RESERVED_TOTAL). [1][3]
Example:
POST https://analyticsdata.googleapis.com/v1beta/properties/PROPERTY_ID:runReport
{
"dateRanges": [{"startDate": "2025-01-01", "endDate": "2025-01-31"}],
"dimensions": [{"name": "country"}],
"metrics": [{"name": "activeUsers"}],
"metricAggregations": ["TOTAL"]
}[1][3]
Response (RunReportResponse)
If requested, the response can include:
totals[]= totaled metric valuesmaximums[]= max metric valuesminimums[]= min metric values
[2]
Where this is documented
metricAggregationsfield onproperties.runReport(RunReportRequest): [1]totals[]field onRunReportResponse: [2]MetricAggregationenum values (TOTAL,MINIMUM,MAXIMUM,COUNT): [3]- A commonly-cited practical note: add
"TOTAL"tometricAggregationsto get totals: [4]
Sources: [1] https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport, [2] https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/RunReportResponse, [3] https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/MetricAggregation, [4] https://stackoverflow.com/questions/75869046/how-to-include-the-totals-field-for-batchrunreports-from-ga4
The totals fallback on line 81 is dead code without metricAggregations in the request.
Per GA4 Data API documentation, the runReport response only populates totals when metricAggregations (e.g., ["TOTAL"]) is explicitly included in the request. The request on lines 61–76 omits this field, so report?.totals will always be empty/undefined, making the fallback on line 81 unreachable. While harmless, either add metricAggregations to the request to make the fallback functional, or remove it for clarity.
♻️ Option A: Add metricAggregations to the request
const report = await this.analytics.queryReportsGA4({
property: propertyId,
data: {
dateRanges: [
{
startDate,
endDate: "today",
},
],
metrics: [
{
name: "screenPageViews",
},
],
+ metricAggregations: [
+ "TOTAL",
+ ],
},
});♻️ Option B: Remove the dead fallback
- const pageViews = report?.rows?.[0]?.metricValues?.[0]?.value
- || report?.totals?.[0]?.metricValues?.[0]?.value
- || "0";
+ const pageViews = report?.rows?.[0]?.metricValues?.[0]?.value || "0";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const pageViews = report?.rows?.[0]?.metricValues?.[0]?.value | |
| || report?.totals?.[0]?.metricValues?.[0]?.value | |
| || "0"; | |
| const pageViews = report?.rows?.[0]?.metricValues?.[0]?.value || "0"; |
🤖 Prompt for AI Agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.
In `@components/google_analytics/sources/page-opened/page-opened.mjs` around lines
80 - 82, The fallback using report?.totals is dead because the runReport request
doesn't include metricAggregations; update the runReport request construction
(the object passed to analyticsDataClient.runReport) to include
metricAggregations: ["TOTAL"] so report.totals will be populated, and then keep
the pageViews computation (report?.rows?.. || report?.totals?.. || "0") as-is;
alternatively, if you prefer removing dead code, delete the report?.totals
fallback from the pageViews assignment that reads from report to rely solely on
report?.rows and "0".
luancazarine
left a comment
There was a problem hiding this comment.
Hi @maycon-pipedream, LGTM! Ready for QA!
For Integration QA: |
|
Hi @maycon-pipedream these are some QA tests at the moment:
Sourcespage-opened
|
|
✅ All tests passed - ready for release!
|
Summary
Migrate the
google_analytics-page-openedtrigger from the deprecated Universal Analytics (UA) Reporting API v4 to the Google Analytics Data API (GA4).Problem
The trigger fails with a 404 Not Found error when attempting to deploy:
Error 404: The requested URL /v4/reports:batchGet was not found on this server.

Root Cause
The component uses the Google Analytics Reporting API v4 (Universal Analytics), which was officially sunset by Google on July 1, 2024. The
reports.batchGetendpoint no longer exists on Google's servers.Affected code path:
page-opened.mjscallsthis.analytics.queryReports(data)google_analytics.app.mjsexecutesclient.reports.batchGet(data)usinganalyticsreporting v4Impact
Solution
Updated the trigger to use the Google Analytics Data API (GA4), which is the current supported API.

Changes
viewIdpropertyqueryReports()queryReportsGA4()ga:pageviewsscreenPageViewsreportRequests[]dateRanges[]+metrics[]reports[0].data.totals[0].values[0]rows[0].metricValues[0].valueBreaking Changes
Existing users will need to:
References
Summary by CodeRabbit
Updates
Chores