fix(ga4): hide every GA4 connect surface until the OAuth app is approved (#466)

This commit is contained in:
Ben Senescu 2026-08-07 22:56:31 -04:00 committed by GitHub
parent eec998a762
commit 45403aa06f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 25 additions and 11 deletions

View File

@ -1,3 +1,5 @@
import { GA4_OAUTH_APP_PENDING } from "@/shared/ga4";
type McpTool = { type McpTool = {
name: string; name: string;
title: string; title: string;
@ -207,11 +209,7 @@ const toolCategories: ToolCategory[] = [
}, },
]; ];
// Google hasn't approved the GA4 OAuth app yet, so connecting fails. const visibleCategories = GA4_OAUTH_APP_PENDING
// Flip to false once the app is approved.
const GA4_TOOLS_HIDDEN = true;
const visibleCategories = GA4_TOOLS_HIDDEN
? toolCategories.filter((cat) => cat.label !== "Google Analytics") ? toolCategories.filter((cat) => cat.label !== "Google Analytics")
: toolCategories; : toolCategories;

View File

@ -25,12 +25,9 @@ import {
refreshDashboardBacklinkSnapshot, refreshDashboardBacklinkSnapshot,
} from "@/serverFunctions/dashboard"; } from "@/serverFunctions/dashboard";
import { setProjectDomain } from "@/serverFunctions/projects"; import { setProjectDomain } from "@/serverFunctions/projects";
import { GA4_OAUTH_APP_PENDING } from "@/shared/ga4";
import type { DashboardHeroStep } from "@/types/schemas/dashboard"; import type { DashboardHeroStep } from "@/types/schemas/dashboard";
// Google hasn't approved the GA4 OAuth app yet, so connecting fails.
// Flip to false once the app is approved.
const GA4_CARD_HIDDEN = true;
const HERO_COPY: Record< const HERO_COPY: Record<
DashboardHeroStep, DashboardHeroStep,
{ title: string; body: string; cta: string } { title: string; body: string; cta: string }
@ -336,7 +333,7 @@ export function DashboardPage({ projectId }: { projectId: string }) {
hasData: gscConnected, hasData: gscConnected,
node: <GscCard projectId={projectId} connected={gscConnected} />, node: <GscCard projectId={projectId} connected={gscConnected} />,
}, },
...(!GA4_CARD_HIDDEN && ...(!GA4_OAUTH_APP_PENDING &&
(ga4Connected || !activation.ga4.cardDismissedAt) (ga4Connected || !activation.ga4.cardDismissedAt)
? [ ? [
{ {

View File

@ -19,7 +19,10 @@ import {
listGa4Properties, listGa4Properties,
setGa4Property, setGa4Property,
} from "@/serverFunctions/ga4"; } from "@/serverFunctions/ga4";
import { GA4_SELF_HOSTED_SETUP_DOCS_URL } from "@/shared/ga4"; import {
GA4_OAUTH_APP_PENDING,
GA4_SELF_HOSTED_SETUP_DOCS_URL,
} from "@/shared/ga4";
export function GoogleAnalyticsConnectionCard({ export function GoogleAnalyticsConnectionCard({
projectId, projectId,
@ -43,6 +46,14 @@ export function GoogleAnalyticsConnectionCard({
}); });
const connection = connectionQuery.data; const connection = connectionQuery.data;
const connected = Boolean(connection?.connected); const connected = Boolean(connection?.connected);
// Hide the hosted connect surface while the OAuth app awaits Google's
// approval, but keep the card for users who already hold a grant so they
// can finish property selection or disconnect.
const hiddenPendingApproval =
GA4_OAUTH_APP_PENDING &&
hosted &&
!connected &&
!connection?.currentUserHasGrant;
const selfHostedNeedsSetup = const selfHostedNeedsSetup =
!hosted && connectionQuery.isSuccess && !connection?.googleOAuthConfigured; !hosted && connectionQuery.isSuccess && !connection?.googleOAuthConfigured;
const showPicker = picking || (connection?.currentUserHasGrant && !connected); const showPicker = picking || (connection?.currentUserHasGrant && !connected);
@ -101,6 +112,8 @@ export function GoogleAnalyticsConnectionCard({
}); });
const handleConnect = () => void startGoogleLink("ga4", window.location.href); const handleConnect = () => void startGoogleLink("ga4", window.location.href);
if (hiddenPendingApproval) return null;
return ( return (
<IntegrationConnectionCard <IntegrationConnectionCard
title="Google Analytics" title="Google Analytics"

View File

@ -1,6 +1,12 @@
/** Better Auth provider ID for the dedicated Google Analytics grant. */ /** Better Auth provider ID for the dedicated Google Analytics grant. */
export const GA4_OAUTH_PROVIDER_ID = "google-analytics"; export const GA4_OAUTH_PROVIDER_ID = "google-analytics";
// Google hasn't approved the GA4 OAuth app yet, so hosted connect attempts
// show Google's "unverified app" warning. Gates every GA4 connect surface;
// flip to false once the app is approved. Self-hosted deployments use their
// own OAuth app, so only hosted mode is gated.
export const GA4_OAUTH_APP_PENDING = true;
export const GA4_OAUTH_SCOPES = [ export const GA4_OAUTH_SCOPES = [
"openid", "openid",
"email", "email",