mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
Merge pull request #14198 from supabase/hi/www-anon-session-id
fix: docs/www anon session id
This commit is contained in:
25 files changed
+316
-71
No files matched your search
@@ -1,2 +1,3 @@
|
||||
export const IS_PLATFORM = process.env.NEXT_PUBLIC_IS_PLATFORM === 'true'
|
||||
export const LOCAL_SUPABASE = process.env.NEXT_PUBLIC_LOCAL_SUPABASE === 'true'
|
||||
export const API_URL = process.env.NEXT_PUBLIC_API_URL
|
||||
@@ -1,7 +1,5 @@
|
||||
interface DataProps {
|
||||
referrer?: string
|
||||
title: string
|
||||
route?: string
|
||||
[prop: string]: any
|
||||
}
|
||||
|
||||
export const post = (url: string, data: DataProps, options = {}) => {
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
"@supabase/supabase-js": "^2.13.0",
|
||||
"algoliasearch": "^4.14.2",
|
||||
"babel": "^6.23.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
"config": "*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { SessionContextProvider } from '@supabase/auth-helpers-react'
|
||||
import { AuthProvider, ThemeProvider } from 'common'
|
||||
import { AuthProvider, ThemeProvider, useGoogleAnalyticsProps } from 'common'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
@@ -10,8 +10,10 @@ import { CommandMenuProvider } from 'ui'
|
||||
import components from '~/components'
|
||||
import Favicons from '~/components/Favicons'
|
||||
import SiteLayout from '~/layouts/SiteLayout'
|
||||
import { IS_PLATFORM, LOCAL_SUPABASE } from '~/lib/constants'
|
||||
import { API_URL, IS_PLATFORM, LOCAL_SUPABASE } from '~/lib/constants'
|
||||
import { post } from '~/lib/fetchWrappers'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import '../styles/ch.scss'
|
||||
import '../styles/main.scss?v=1.0.0'
|
||||
import '../styles/new-docs.scss'
|
||||
@@ -19,19 +21,33 @@ import '../styles/prism-okaidia.scss'
|
||||
|
||||
function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
const router = useRouter()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
const [supabase] = useState(() =>
|
||||
IS_PLATFORM || LOCAL_SUPABASE ? createBrowserSupabaseClient() : undefined
|
||||
)
|
||||
|
||||
function handlePageTelemetry(route: string) {
|
||||
return post(`https://api.supabase.io/platform/telemetry/page`, {
|
||||
return post(`${API_URL}/telemetry/page`, {
|
||||
referrer: document.referrer,
|
||||
title: document.title,
|
||||
route,
|
||||
ga: {
|
||||
screen_resolution: googleAnalyticsProps?.screenResolution,
|
||||
language: googleAnalyticsProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Generate browser session id for anon tracking
|
||||
BrowserTabTracker.initialize({
|
||||
storageKey: 'supabase.browser.session',
|
||||
sessionIdGenerator: () => uuidv4(),
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
function handleRouteChange(url: string) {
|
||||
/*
|
||||
|
||||
@@ -1,12 +1,52 @@
|
||||
import { Button, Badge, IconArrowRight } from 'ui'
|
||||
import SectionHeader from 'components/UI/SectionHeader'
|
||||
import { Badge } from 'ui'
|
||||
import Solutions from 'data/Solutions.json'
|
||||
import Link from 'next/link'
|
||||
import Telemetry from '~/lib/telemetry'
|
||||
import gaEvents from '~/lib/gaEvents'
|
||||
import SectionContainer from '../Layouts/SectionContainer'
|
||||
import ProductIcon from '../ProductIcon'
|
||||
import TextLink from '../TextLink'
|
||||
import { useGoogleAnalyticsProps } from 'common/hooks/useGoogleAnalyticsProps'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const Features = () => {
|
||||
const router = useRouter()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
const sendTelemetryEvent = async (product: any) => {
|
||||
switch (product) {
|
||||
case 'Database':
|
||||
return await Telemetry.sendEvent(
|
||||
gaEvents['www_hp_subhero_products_database'],
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
case 'Authentication':
|
||||
return await Telemetry.sendEvent(
|
||||
gaEvents['www_hp_subhero_products_auth'],
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
case 'Storage':
|
||||
return await Telemetry.sendEvent(
|
||||
gaEvents['www_hp_subhero_products_storage'],
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
case 'Edge Functions':
|
||||
return await Telemetry.sendEvent(
|
||||
gaEvents['www_hp_subhero_products_edgeFunctions'],
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
case 'Realtime':
|
||||
return await Telemetry.sendEvent(
|
||||
gaEvents['www_hp_subhero_products_realtime'],
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const IconSections = Object.values(Solutions).map((solution: any) => {
|
||||
const { name, description, icon, label, url } = solution
|
||||
if (solution.name === 'Realtime') return null
|
||||
@@ -24,7 +64,13 @@ const Features = () => {
|
||||
<Badge dot>{label}</Badge>
|
||||
</div>
|
||||
)}
|
||||
{url && <TextLink label={label ? 'Get notified' : 'Learn more'} url={url} />}
|
||||
{url && (
|
||||
<TextLink
|
||||
label={label ? 'Get notified' : 'Learn more'}
|
||||
url={url}
|
||||
onClick={() => sendTelemetryEvent(name)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { Button, IconBookOpen, Space } from 'ui'
|
||||
import Link from 'next/link'
|
||||
import { Button, IconBookOpen } from 'ui'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import SectionContainer from './Layouts/SectionContainer'
|
||||
import Telemetry, { GoogleAnalyticsEvent } from '~/lib/telemetry'
|
||||
import gaEvents from '~/lib/gaEvents'
|
||||
import { useGoogleAnalyticsProps } from 'common/hooks/useGoogleAnalyticsProps'
|
||||
|
||||
const Hero = () => {
|
||||
const { basePath } = useRouter()
|
||||
const router = useRouter()
|
||||
const { basePath } = router
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
const sendTelemetryEvent = async (event: GoogleAnalyticsEvent) => {
|
||||
await Telemetry.sendEvent(event, googleAnalyticsProps, router)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden">
|
||||
@@ -40,14 +49,16 @@ const Hero = () => {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Link href="https://app.supabase.com" as="https://app.supabase.com" passHref>
|
||||
<a>
|
||||
<a onClick={() => sendTelemetryEvent(gaEvents['www_hp_hero_startProject'])}>
|
||||
<Button size="small" className="text-white">
|
||||
Start your project
|
||||
</Button>
|
||||
</a>
|
||||
</Link>
|
||||
<Link href="/docs" as="/docs" passHref>
|
||||
<a>
|
||||
<a
|
||||
onClick={() => sendTelemetryEvent(gaEvents['www_hp_hero_documentation'])}
|
||||
>
|
||||
<Button size="small" type="default" icon={<IconBookOpen />}>
|
||||
Documentation
|
||||
</Button>
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { IconArrowRight, IconChevronRight } from 'ui'
|
||||
import { IconChevronRight } from 'ui'
|
||||
import Link from 'next/link'
|
||||
|
||||
function TextLink({ url, label }: any) {
|
||||
function TextLink({ url = '', label, ...props }: any) {
|
||||
return (
|
||||
<a
|
||||
href={url}
|
||||
className="text-scale-1100 hover:text-scale-1200 mt-3 block cursor-pointer text-sm"
|
||||
>
|
||||
<div className="group flex items-center gap-1">
|
||||
<span className="sr-only">{`${label} about ${url}`}</span>
|
||||
<span>{label}</span>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<IconChevronRight size={14} strokeWidth={2} />
|
||||
<Link href={url} passHref>
|
||||
<a
|
||||
className="text-scale-1100 hover:text-scale-1200 mt-3 block cursor-pointer text-sm"
|
||||
{...props}
|
||||
>
|
||||
<div className="group flex items-center gap-1">
|
||||
<span className="sr-only">{`${label} about ${url}`}</span>
|
||||
<span>{label}</span>
|
||||
<div className="transition-all group-hover:ml-0.5">
|
||||
<IconChevronRight size={14} strokeWidth={2} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,14 +23,6 @@
|
||||
"label": "",
|
||||
"url": "/storage"
|
||||
},
|
||||
"realtime": {
|
||||
"name": "Realtime",
|
||||
"icon": "M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59",
|
||||
"description": "Store, organize, and serve large files. Any media, including videos and images.",
|
||||
"description_short": "",
|
||||
"label": "",
|
||||
"url": "/storage"
|
||||
},
|
||||
"edge-functions": {
|
||||
"name": "Edge Functions",
|
||||
"icon": "M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
export const APP_NAME = 'Supabase'
|
||||
export const DESCRIPTION = 'The Open Source Alternative to Firebase.'
|
||||
export const IS_PROD = process.env.NEXT_PUBLIC_VERCEL_ENV === 'production'
|
||||
export const IS_PREVIEW = process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview'
|
||||
export const API_URL = process.env.NEXT_PUBLIC_API_URL
|
||||
|
||||
// Launch Weeek
|
||||
export const SAMPLE_TICKET_NUMBER = 1234
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
interface DataProps {
|
||||
referrer?: string
|
||||
title: string
|
||||
route?: string
|
||||
[prop: string]: any
|
||||
}
|
||||
|
||||
export const post = (url: string, data: DataProps, options = {}) => {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { GoogleAnalyticsEvent } from './telemetry'
|
||||
|
||||
interface GoogleAnalyticsEventType {
|
||||
[key: string]: GoogleAnalyticsEvent
|
||||
}
|
||||
|
||||
const GoogleAnalyticsEvents: GoogleAnalyticsEventType = {
|
||||
www_hp_hero_startProject: {
|
||||
action: 'www_hp_hero_startProject',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_hero_documentation: {
|
||||
action: 'www_hp_hero_documentation',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_subhero_products_database: {
|
||||
action: 'www_hp_subhero_products_database',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_subhero_products_auth: {
|
||||
action: 'www_hp_subhero_products_auth',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_subhero_products_storage: {
|
||||
action: 'www_hp_subhero_products_storage',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_subhero_products_edgeFunctions: {
|
||||
action: 'www_hp_subhero_products_edgeFunctions',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
www_hp_subhero_products_realtime: {
|
||||
action: 'www_hp_subhero_products_realtime',
|
||||
category: 'link',
|
||||
label: '',
|
||||
},
|
||||
}
|
||||
|
||||
export default GoogleAnalyticsEvents
|
||||
@@ -0,0 +1,48 @@
|
||||
import { post } from '~/lib/fetchWrapper'
|
||||
import { API_URL, IS_PROD, IS_PREVIEW } from 'lib/constants'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { NextRouter } from 'next/router'
|
||||
|
||||
export interface GoogleAnalyticsEvent {
|
||||
category: string
|
||||
action: string
|
||||
label: string
|
||||
value?: string
|
||||
}
|
||||
|
||||
export interface GoogleAnalyticsProps {
|
||||
screenResolution?: string
|
||||
language: string
|
||||
}
|
||||
|
||||
// This event is the same as in studio/lib/telemetry.tx
|
||||
// but uses different ENV variables for www
|
||||
|
||||
const sendEvent = (
|
||||
event: GoogleAnalyticsEvent,
|
||||
gaProps: GoogleAnalyticsProps,
|
||||
router: NextRouter
|
||||
) => {
|
||||
if (!IS_PROD && !IS_PREVIEW) return
|
||||
|
||||
const { category, action, label, value } = event
|
||||
|
||||
return post(`${API_URL}/telemetry/event`, {
|
||||
action: action,
|
||||
category: category,
|
||||
label: label,
|
||||
value: value,
|
||||
page_referrer: document?.referrer,
|
||||
page_title: document?.title,
|
||||
page_location: router.asPath,
|
||||
ga: {
|
||||
screen_resolution: gaProps?.screenResolution,
|
||||
language: gaProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
sendEvent,
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
"@next/mdx": "^12.3.2",
|
||||
"@supabase/auth-ui-react": "^0.1.6",
|
||||
"@supabase/supabase-js": "^2.13.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"cobe": "^0.6.2",
|
||||
"common": "*",
|
||||
|
||||
+20
-4
@@ -1,25 +1,41 @@
|
||||
import { APP_NAME, DESCRIPTION } from 'lib/constants'
|
||||
import { API_URL, APP_NAME, DESCRIPTION } from 'lib/constants'
|
||||
import { DefaultSeo } from 'next-seo'
|
||||
import { AppProps } from 'next/app'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import Meta from '~/components/Favicons'
|
||||
import '../styles/index.css'
|
||||
import { post } from './../lib/fetchWrapper'
|
||||
import { AuthProvider, ThemeProvider } from 'common'
|
||||
import { post } from '~/lib/fetchWrapper'
|
||||
import { AuthProvider, ThemeProvider, useGoogleAnalyticsProps } from 'common'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import Head from 'next/head'
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
const router = useRouter()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
function handlePageTelemetry(route: string) {
|
||||
return post(`https://api.supabase.io/platform/telemetry/page`, {
|
||||
return post(`${API_URL}/telemetry/page`, {
|
||||
referrer: document.referrer,
|
||||
title: document.title,
|
||||
route,
|
||||
ga: {
|
||||
screen_resolution: googleAnalyticsProps?.screenResolution,
|
||||
language: googleAnalyticsProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Generate browser session id for anon tracking
|
||||
BrowserTabTracker.initialize({
|
||||
storageKey: 'supabase.browser.session',
|
||||
sessionIdGenerator: () => uuidv4(),
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
function handleRouteChange(url: string) {
|
||||
handlePageTelemetry(url)
|
||||
|
||||
Generated
+37
@@ -51,6 +51,7 @@
|
||||
"@supabase/supabase-js": "^2.13.0",
|
||||
"algoliasearch": "^4.14.2",
|
||||
"babel": "^6.23.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
"config": "*",
|
||||
@@ -673,6 +674,7 @@
|
||||
"@next/mdx": "^12.3.2",
|
||||
"@supabase/auth-ui-react": "^0.1.6",
|
||||
"@supabase/supabase-js": "^2.13.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"cobe": "^0.6.2",
|
||||
"common": "*",
|
||||
@@ -12807,6 +12809,22 @@
|
||||
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/browser-session-tabs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-session-tabs/-/browser-session-tabs-3.0.0.tgz",
|
||||
"integrity": "sha512-HBJWkCbcDYFL+hlSGld54SF1SgaiSXnw9vaTPdDeOxT9HCTFt3hVdArIroQ3HDhh9vhqkbl6TkMjTFok0ZfwIA==",
|
||||
"dependencies": {
|
||||
"js-cookie": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/browser-session-tabs/node_modules/js-cookie": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
|
||||
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
@@ -39189,6 +39207,7 @@
|
||||
"analytics-node": "^3.5.0",
|
||||
"awesome-debounce-promise": "^2.1.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clipboard": "^2.0.8",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
@@ -48910,6 +48929,21 @@
|
||||
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
|
||||
"dev": true
|
||||
},
|
||||
"browser-session-tabs": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-session-tabs/-/browser-session-tabs-3.0.0.tgz",
|
||||
"integrity": "sha512-HBJWkCbcDYFL+hlSGld54SF1SgaiSXnw9vaTPdDeOxT9HCTFt3hVdArIroQ3HDhh9vhqkbl6TkMjTFok0ZfwIA==",
|
||||
"requires": {
|
||||
"js-cookie": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-cookie": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
|
||||
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
@@ -51538,6 +51572,7 @@
|
||||
"@types/react": "17.0.39",
|
||||
"algoliasearch": "^4.14.2",
|
||||
"babel": "^6.23.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
"config": "*",
|
||||
@@ -66421,6 +66456,7 @@
|
||||
"aws-sdk": "^2.1354.0",
|
||||
"babel-loader": "^8.2.3",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clipboard": "^2.0.8",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
@@ -69873,6 +69909,7 @@
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/react-syntax-highlighter": "^13.5.2",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"cobe": "^0.6.2",
|
||||
"common": "*",
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './useBreakpoint'
|
||||
export * from './useParams'
|
||||
export * from './useGoogleAnalyticsProps'
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const isBrowser = typeof window !== 'undefined'
|
||||
|
||||
export function useGoogleAnalyticsProps() {
|
||||
const { locale } = useRouter()
|
||||
|
||||
return {
|
||||
screenResolution: isBrowser ? `${window.innerWidth}x${window.innerHeight}` : undefined,
|
||||
language: locale ?? 'en-US',
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { useProfileQuery } from 'data/profile/profile-query'
|
||||
import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants'
|
||||
import SQLCard from './SQLCard'
|
||||
import { createSqlSnippetSkeleton } from '../SQLEditor.utils'
|
||||
import { useParams } from 'common'
|
||||
import { useGoogleAnalyticsProps, useParams } from 'common'
|
||||
import { useRouter } from 'next/router'
|
||||
import { SqlSnippet } from 'data/content/sql-snippets-query'
|
||||
import { useSqlEditorStateSnapshot } from 'state/sql-editor'
|
||||
@@ -21,6 +21,7 @@ const SQLTemplates = observer(() => {
|
||||
const { data: profile } = useProfileQuery()
|
||||
const [sql, quickStart] = partition(SQL_TEMPLATES, { type: 'template' })
|
||||
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
const snap = useSqlEditorStateSnapshot()
|
||||
const canCreateSQLSnippet = checkPermissions(PermissionAction.CREATE, 'user_content', {
|
||||
resource: { type: 'sql', owner_id: profile?.id },
|
||||
@@ -77,7 +78,8 @@ const SQLTemplates = observer(() => {
|
||||
action: 'script_clicked',
|
||||
label: x.title,
|
||||
},
|
||||
ui.googleAnalyticsProps
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
}}
|
||||
/>
|
||||
@@ -111,7 +113,8 @@ const SQLTemplates = observer(() => {
|
||||
action: 'quickstart_clicked',
|
||||
label: x.title,
|
||||
},
|
||||
ui.googleAnalyticsProps
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { CSVLink } from 'react-csv'
|
||||
import { useSqlEditorStateSnapshot } from 'state/sql-editor'
|
||||
// @ts-ignore
|
||||
import MarkdownTable from 'markdown-table'
|
||||
import { useGoogleAnalyticsProps } from 'common'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export type ResultsDropdownProps = {
|
||||
id: string
|
||||
@@ -17,9 +19,11 @@ export type ResultsDropdownProps = {
|
||||
const ResultsDropdown = ({ id }: ResultsDropdownProps) => {
|
||||
const { project } = useProjectContext()
|
||||
const snap = useSqlEditorStateSnapshot()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
const result = snap.results?.[id]?.[0] ?? undefined
|
||||
const { ui } = useStore()
|
||||
const csvRef = useRef<CSVLink & HTMLAnchorElement & { link: HTMLAnchorElement }>(null)
|
||||
const router = useRouter()
|
||||
|
||||
const csvData = useMemo(
|
||||
() => (result?.rows ? compact(Array.from(result.rows || [])) : ''),
|
||||
@@ -30,7 +34,8 @@ const ResultsDropdown = ({ id }: ResultsDropdownProps) => {
|
||||
csvRef.current?.link.click()
|
||||
Telemetry.sendEvent(
|
||||
{ category: 'sql_editor', action: 'sql_download_csv', label: '' },
|
||||
ui.googleAnalyticsProps
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,7 +58,8 @@ const ResultsDropdown = ({ id }: ResultsDropdownProps) => {
|
||||
ui.setNotification({ category: 'success', message: 'Copied results to clipboard' })
|
||||
Telemetry.sendEvent(
|
||||
{ category: 'sql_editor', action: 'sql_copy_as_markdown', label: '' },
|
||||
ui.googleAnalyticsProps
|
||||
googleAnalyticsProps,
|
||||
router
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useStore } from 'hooks'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { useGoogleAnalyticsProps } from 'common'
|
||||
import { post } from 'lib/common/fetch'
|
||||
import { API_URL, IS_PLATFORM } from 'lib/constants'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
@@ -25,7 +26,7 @@ function sanitizePageViewRoute(_route?: string) {
|
||||
|
||||
const PageTelemetry: FC = ({ children }) => {
|
||||
const router = useRouter()
|
||||
const { ui } = useStore()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
useEffect(() => {
|
||||
function handleRouteChange(url: string) {
|
||||
@@ -71,8 +72,9 @@ const PageTelemetry: FC = ({ children }) => {
|
||||
title: document.title,
|
||||
route,
|
||||
ga: {
|
||||
screen_resolution: ui.googleAnalyticsProps?.screenResolution,
|
||||
language: ui.googleAnalyticsProps?.language,
|
||||
screen_resolution: googleAnalyticsProps?.screenResolution,
|
||||
language: googleAnalyticsProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,18 +1,20 @@
|
||||
import {
|
||||
AuthContext as AuthContextInternal,
|
||||
AuthProvider as AuthProviderInternal,
|
||||
AuthProviderProps,
|
||||
gotrueClient,
|
||||
useGoogleAnalyticsProps,
|
||||
} from 'common'
|
||||
import { useProfileQuery } from 'data/profile/profile-query'
|
||||
import { useStore } from 'hooks'
|
||||
import { PropsWithChildren, useEffect } from 'react'
|
||||
import { GOTRUE_ERRORS, IS_PLATFORM } from './constants'
|
||||
import Telemetry from 'lib/telemetry'
|
||||
|
||||
export const AuthContext = AuthContextInternal
|
||||
|
||||
export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const { ui, app } = useStore()
|
||||
const googleAnalyticsProps = useGoogleAnalyticsProps()
|
||||
|
||||
// Check for unverified GitHub users after a GitHub sign in
|
||||
useEffect(() => {
|
||||
@@ -34,7 +36,7 @@ export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
// Track telemetry for the current user
|
||||
useProfileQuery({
|
||||
onSuccess(profile) {
|
||||
ui.setProfile(profile)
|
||||
Telemetry.sendIdentify(profile, googleAnalyticsProps)
|
||||
|
||||
// [Joshen] Temp fix: For new users, the GET profile call also creates a default org
|
||||
// But because the dashboard's logged in state is using gotrue as the source of truth
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { post } from 'lib/common/fetch'
|
||||
import { API_URL, IS_PLATFORM } from 'lib/constants'
|
||||
import { User } from 'types'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { NextRouter } from 'next/router'
|
||||
|
||||
export interface GoogleAnalyticsProps {
|
||||
screenResolution?: string
|
||||
@@ -14,7 +16,8 @@ const sendEvent = (
|
||||
label: string
|
||||
value?: string
|
||||
},
|
||||
gaProps?: GoogleAnalyticsProps
|
||||
gaProps: GoogleAnalyticsProps,
|
||||
router: NextRouter
|
||||
) => {
|
||||
if (!IS_PLATFORM) return
|
||||
|
||||
@@ -25,9 +28,13 @@ const sendEvent = (
|
||||
category: category,
|
||||
label: label,
|
||||
value: value,
|
||||
page_referrer: document?.referrer,
|
||||
page_title: document?.title,
|
||||
page_location: router.asPath,
|
||||
ga: {
|
||||
screen_resolution: gaProps?.screenResolution,
|
||||
language: gaProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -44,6 +51,7 @@ const sendIdentify = (user: User, gaProps?: GoogleAnalyticsProps) => {
|
||||
ga: {
|
||||
screen_resolution: gaProps?.screenResolution,
|
||||
language: gaProps?.language,
|
||||
session_id: BrowserTabTracker.sessionId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"analytics-node": "^3.5.0",
|
||||
"awesome-debounce-promise": "^2.1.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"browser-session-tabs": "^3.0.0",
|
||||
"clipboard": "^2.0.8",
|
||||
"clsx": "^1.2.1",
|
||||
"common": "*",
|
||||
|
||||
@@ -50,6 +50,8 @@ import Favicons from 'components/head/Favicons'
|
||||
import { IS_PLATFORM } from 'lib/constants'
|
||||
import { SessionContextProvider } from '@supabase/auth-helpers-react'
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { BrowserTabTracker } from 'browser-session-tabs'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
@@ -74,6 +76,14 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) {
|
||||
|
||||
const getSavingState = () => rootStore.content.savingState
|
||||
|
||||
useEffect(() => {
|
||||
// Generate browser session id for anon tracking
|
||||
BrowserTabTracker.initialize({
|
||||
storageKey: 'supabase.browser.session',
|
||||
sessionIdGenerator: () => uuidv4(),
|
||||
})
|
||||
}, [])
|
||||
|
||||
// prompt the user if they try and leave with unsaved content store changes
|
||||
useEffect(() => {
|
||||
const warningText = 'You have unsaved changes - are you sure you wish to leave this page?'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { uuidv4 } from 'lib/helpers'
|
||||
import { action, makeAutoObservable } from 'mobx'
|
||||
import { Project, Notification, User, Organization, ProjectBase, Permission } from 'types'
|
||||
import { Project, Notification, Organization, ProjectBase, Permission } from 'types'
|
||||
import { IRootStore } from './RootStore'
|
||||
import Telemetry, { GoogleAnalyticsProps } from 'lib/telemetry'
|
||||
|
||||
export interface IUiStore {
|
||||
language: 'en-US'
|
||||
@@ -12,12 +11,10 @@ export interface IUiStore {
|
||||
selectedOrganization?: Organization
|
||||
notification?: Notification
|
||||
permissions?: Permission[]
|
||||
googleAnalyticsProps?: GoogleAnalyticsProps
|
||||
load: () => void
|
||||
setProjectRef: (ref?: string) => void
|
||||
setOrganizationSlug: (slug?: string) => void
|
||||
setNotification: (notification: Notification) => string
|
||||
setProfile: (value: User) => void
|
||||
setPermissions: (permissions?: Permission[]) => void
|
||||
}
|
||||
export default class UiStore implements IUiStore {
|
||||
@@ -83,14 +80,6 @@ export default class UiStore implements IUiStore {
|
||||
return undefined
|
||||
}
|
||||
|
||||
get googleAnalyticsProps() {
|
||||
return {
|
||||
screenResolution:
|
||||
typeof window !== 'undefined' ? `${window.innerWidth}x${window.innerHeight}` : undefined,
|
||||
language: this.language,
|
||||
}
|
||||
}
|
||||
|
||||
load() {
|
||||
if (typeof window === 'undefined') return
|
||||
}
|
||||
@@ -109,10 +98,6 @@ export default class UiStore implements IUiStore {
|
||||
return id
|
||||
}
|
||||
|
||||
setProfile(value: User) {
|
||||
Telemetry.sendIdentify(value, this.googleAnalyticsProps)
|
||||
}
|
||||
|
||||
setPermissions(permissions?: any) {
|
||||
this.permissions = permissions
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user