-
Notifications
You must be signed in to change notification settings - Fork 2.4k
fix: add event_callback pattern to Google Ads conversion tracking #9011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add event_callback to trackGoogleAdsConversion() to ensure conversion ping completes before navigation - Update CTA button handlers to prevent default navigation and pass target URL - Add fallback timeout for reliability in case callback does not fire - Improve documentation with usage examples
- Apply same event_callback pattern to PR Fixer CTA buttons - Fixes TypeScript errors from updated trackGoogleAdsConversion signature
|
Review completed. Found 5 issues that need attention:
Mention @roomote in a comment to trigger your PR Fixer agent and make changes to this pull request. |
|
🚀 Preview deployed! Your changes have been deployed to Vercel: Preview URL: https://roo-code-website-awxpoafdf-roo-code.vercel.app This preview will be updated automatically when you push new commits to this PR. |
| export function trackGoogleAdsConversion(targetUrl?: string) { | ||
| if (typeof window !== "undefined" && window.gtag) { | ||
| // Callback to handle navigation after conversion tracking | ||
| const callback = () => { | ||
| if (targetUrl) { | ||
| window.location.href = targetUrl | ||
| } | ||
| } | ||
|
|
||
| window.gtag("event", "conversion", { | ||
| send_to: "AW-17391954825/VtOZCJe_77MbEInXkOVA", | ||
| value: 10.0, | ||
| currency: "USD", | ||
| event_callback: callback, | ||
| }) | ||
|
|
||
| // Fallback timeout in case event_callback doesn't fire (network issues, etc.) | ||
| // This ensures navigation still happens even if tracking fails | ||
| setTimeout(callback, 1000) | ||
| } else if (targetUrl) { | ||
| // If gtag is not available, navigate immediately | ||
| window.location.href = targetUrl | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The callback can execute twice: once from event_callback and once from setTimeout. If the tracking completes before 1 second (the common case), both navigation attempts will fire. This should use a flag to ensure the callback only executes once.
| export function trackGoogleAdsConversion(targetUrl?: string) { | |
| if (typeof window !== "undefined" && window.gtag) { | |
| // Callback to handle navigation after conversion tracking | |
| const callback = () => { | |
| if (targetUrl) { | |
| window.location.href = targetUrl | |
| } | |
| } | |
| window.gtag("event", "conversion", { | |
| send_to: "AW-17391954825/VtOZCJe_77MbEInXkOVA", | |
| value: 10.0, | |
| currency: "USD", | |
| event_callback: callback, | |
| }) | |
| // Fallback timeout in case event_callback doesn't fire (network issues, etc.) | |
| // This ensures navigation still happens even if tracking fails | |
| setTimeout(callback, 1000) | |
| } else if (targetUrl) { | |
| // If gtag is not available, navigate immediately | |
| window.location.href = targetUrl | |
| } | |
| } | |
| export function trackGoogleAdsConversion(targetUrl?: string) { | |
| if (typeof window !== "undefined" && window.gtag) { | |
| let hasNavigated = false | |
| // Callback to handle navigation after conversion tracking | |
| const callback = () => { | |
| if (!hasNavigated && targetUrl) { | |
| hasNavigated = true | |
| window.location.href = targetUrl | |
| } | |
| } | |
| window.gtag("event", "conversion", { | |
| send_to: "AW-17391954825/VtOZCJe_77MbEInXkOVA", | |
| value: 10.0, | |
| currency: "USD", | |
| event_callback: callback, | |
| }) | |
| // Fallback timeout in case event_callback doesn't fire (network issues, etc.) | |
| // This ensures navigation still happens even if tracking fails | |
| setTimeout(callback, 1000) | |
| } else if (targetUrl) { | |
| // If gtag is not available, navigate immediately | |
| window.location.href = targetUrl | |
| } | |
| } |
Fix it with Roo Code or mention @roomote and request a fix.
| onClick={(e) => { | ||
| e.preventDefault() | ||
| trackGoogleAdsConversion(EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO) | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the link behavior from opening in a new tab to navigating the current tab. The anchor has target="_blank" but e.preventDefault() + window.location.href overrides this, breaking the original user experience of keeping the marketing site open while opening the signup page in a new tab. Use window.open(targetUrl, '_blank') to preserve the new tab behavior.
Fix it with Roo Code or mention @roomote and request a fix.
| onClick={(e) => { | ||
| e.preventDefault() | ||
| trackGoogleAdsConversion(EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO) | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue: this changes the link behavior from opening in a new tab to navigating the current tab. The anchor has target="_blank" but e.preventDefault() + window.location.href overrides this. Use window.open(targetUrl, '_blank') to preserve the new tab behavior.
Fix it with Roo Code or mention @roomote and request a fix.
| onClick={(e) => { | ||
| e.preventDefault() | ||
| trackGoogleAdsConversion(EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO) | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue: this changes the link behavior from opening in a new tab to navigating the current tab. The anchor has target="_blank" but e.preventDefault() + window.location.href overrides this. Use window.open(targetUrl, '_blank') to preserve the new tab behavior.
Fix it with Roo Code or mention @roomote and request a fix.
| onClick={(e) => { | ||
| e.preventDefault() | ||
| trackGoogleAdsConversion(EXTERNAL_LINKS.CLOUD_APP_SIGNUP_PRO) | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue: this changes the link behavior from opening in a new tab to navigating the current tab. The anchor has target="_blank" but e.preventDefault() + window.location.href overrides this. Use window.open(targetUrl, '_blank') to preserve the new tab behavior.
Fix it with Roo Code or mention @roomote and request a fix.
Summary
This PR adds the pattern to Google Ads conversion tracking to prevent lost conversions during navigation.
Context
The Slack analysis claimed that Google Ads conversion tracking wasn't working due to missing gtag.js setup and Consent Mode v2 configuration. However, upon investigation, the existing implementation was already comprehensive and correct:
✅ Google tag (gtag.js) is loaded via GoogleAnalyticsProvider
✅ Consent Mode v2 is properly configured with all required fields
✅ Cookie consent properly updates ad consent on accept
✅ Conversion tracking is implemented with correct send_to parameter
The Actual Issue
The only valid concern was the missing event_callback pattern. Without it, when users click CTA buttons, the page navigation can occur before the conversion tracking network request completes, resulting in lost conversions.
Changes
Modified Files
apps/web-roo-code/src/lib/analytics/google-ads.tstargetUrlparameter totrackGoogleAdsConversion()event_callbackto handle navigation after tracking completesapps/web-roo-code/src/app/reviewer/ReviewerContent.tsxapps/web-roo-code/src/app/pr-fixer/PrFixerContent.tsxBenefits
Testing
The implementation follows Google's official recommendation for click conversion tracking with event callbacks.
Important
Adds
event_callbackpattern to Google Ads conversion tracking to ensure conversions are tracked before navigation, preventing lost conversions.event_callbackpattern totrackGoogleAdsConversion()ingoogle-ads.tsto ensure conversion tracking completes before navigation.trackGoogleAdsConversion()for reliability.ReviewerContent.tsx: Updates CTA button click handlers to prevent default navigation and use callback-based navigation.PrFixerContent.tsx: Applies the same pattern to CTA buttons for consistency.This description was created by
for e532fad. You can customize this summary. It will automatically update as commits are pushed.