Google OAuth verification: privacy policy disclosures + GA4 reviewer access (#488)

* Add Google user data disclosures and Limited Use statement to privacy policy

* Show GA4 connect surfaces to the Google OAuth verification reviewer account

* List OpenAI as a potential AI model provider in the privacy policy
This commit is contained in:
Ben Senescu 2026-08-15 18:27:59 -04:00 committed by GitHub
parent c8b3eb9b0a
commit 61ebdb05ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 12 deletions

View File

@ -26,7 +26,8 @@ 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 { useSession } from "@/lib/auth-client";
import { isGa4ConnectAvailable } from "@/shared/ga4";
import type { DashboardHeroStep } from "@/types/schemas/dashboard"; import type { DashboardHeroStep } from "@/types/schemas/dashboard";
const HERO_COPY: Record< const HERO_COPY: Record<
@ -235,6 +236,7 @@ function OnboardingChecklist({
export function DashboardPage({ projectId }: { projectId: string }) { export function DashboardPage({ projectId }: { projectId: string }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data: session } = useSession();
const activationQuery = useQuery({ const activationQuery = useQuery({
queryKey: ["dashboardActivation", projectId], queryKey: ["dashboardActivation", projectId],
@ -336,7 +338,7 @@ export function DashboardPage({ projectId }: { projectId: string }) {
hasData: gscConnected, hasData: gscConnected,
node: <GscCard projectId={projectId} connected={gscConnected} />, node: <GscCard projectId={projectId} connected={gscConnected} />,
}, },
...(!GA4_OAUTH_APP_PENDING && ...(isGa4ConnectAvailable(session?.user?.email) &&
(ga4Connected || !activation.ga4.cardDismissedAt) (ga4Connected || !activation.ga4.cardDismissedAt)
? [ ? [
{ {

View File

@ -19,9 +19,10 @@ import {
listGa4Properties, listGa4Properties,
setGa4Property, setGa4Property,
} from "@/serverFunctions/ga4"; } from "@/serverFunctions/ga4";
import { useSession } from "@/lib/auth-client";
import { import {
GA4_OAUTH_APP_PENDING,
GA4_SELF_HOSTED_SETUP_DOCS_URL, GA4_SELF_HOSTED_SETUP_DOCS_URL,
isGa4ConnectAvailable,
} from "@/shared/ga4"; } from "@/shared/ga4";
export function GoogleAnalyticsConnectionCard({ export function GoogleAnalyticsConnectionCard({
@ -37,6 +38,7 @@ export function GoogleAnalyticsConnectionCard({
}) { }) {
const hosted = isHostedClientAuthMode(); const hosted = isHostedClientAuthMode();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data: session } = useSession();
const [picking, setPicking] = React.useState(false); const [picking, setPicking] = React.useState(false);
const [selection, setSelection] = React.useState<Ga4PropertySelection | null>( const [selection, setSelection] = React.useState<Ga4PropertySelection | null>(
null, null,
@ -52,7 +54,7 @@ export function GoogleAnalyticsConnectionCard({
// approval, but keep the card for users who already hold a grant so they // approval, but keep the card for users who already hold a grant so they
// can finish property selection or disconnect. // can finish property selection or disconnect.
const hiddenPendingApproval = const hiddenPendingApproval =
GA4_OAUTH_APP_PENDING && !isGa4ConnectAvailable(session?.user?.email) &&
hosted && hosted &&
!connected && !connected &&
!connection?.currentUserHasGrant; !connection?.currentUserHasGrant;

View File

@ -7,6 +7,19 @@ export const GA4_OAUTH_PROVIDER_ID = "google-analytics";
// own OAuth app, so only hosted mode is gated. // own OAuth app, so only hosted mode is gated.
export const GA4_OAUTH_APP_PENDING = true; export const GA4_OAUTH_APP_PENDING = true;
// Google's OAuth verification reviewer tests with this account, so the GA4
// connect/disconnect surfaces stay visible for it while the app is pending
// approval. MCP tool registration stays gated for everyone until approval.
const GA4_OAUTH_REVIEWER_EMAILS = new Set(["walkthrough@everyapp.dev"]);
/** Whether GA4 connect surfaces are visible to this user despite the pending gate. */
export function isGa4ConnectAvailable(
email: string | null | undefined,
): boolean {
if (!GA4_OAUTH_APP_PENDING) return true;
return email != null && GA4_OAUTH_REVIEWER_EMAILS.has(email);
}
export const GA4_OAUTH_SCOPES = [ export const GA4_OAUTH_SCOPES = [
"openid", "openid",
"email", "email",

File diff suppressed because one or more lines are too long