├── tinybird ├── .env.local ├── .gitignore ├── datasources │ ├── analytics_pages_mv.datasource │ ├── analytics_sources_mv.datasource │ ├── tenant_domains_mv.datasource │ ├── tenant_actions_mv.datasource │ ├── analytics_sessions_mv.datasource │ └── analytics_events.datasource ├── endpoints │ ├── current_visitors.pipe │ ├── domain.pipe │ ├── domains.pipe │ ├── actions.pipe │ ├── trend.pipe │ ├── analytics_hits.pipe │ ├── top_devices.pipe │ ├── top_browsers.pipe │ ├── top_locations.pipe │ ├── top_pages.pipe │ └── top_sources.pipe ├── materializations │ ├── tenant_domains.pipe │ ├── analytics_pages.pipe │ ├── analytics_sources.pipe │ ├── analytics_sessions.pipe │ └── tenant_actions.pipe ├── copies │ └── random_data_generator.pipe ├── web_vitals │ └── endpoints │ │ ├── web_vitals_timeseries.pipe │ │ └── web_vitals_current.pipe ├── README.md ├── fixtures │ ├── analytics_events.sql.backup │ └── analytics_events.sql └── mock │ └── schema.json ├── middleware ├── .vercelignore ├── .gitignore ├── .npmignore ├── src │ └── index.html ├── package.json └── api │ └── tracking.js ├── .gitignore ├── dashboard-template.png ├── assets └── img │ ├── data_flow.png │ ├── repo-banner.png │ ├── banner_snippet.png │ ├── events-incoming.png │ └── banner_dashboard.png ├── dashboard ├── public │ ├── banner.png │ ├── chart.png │ ├── favicon.ico │ ├── fallback-logo.png │ ├── fonts │ │ └── Inter-roman-latin.var.woff2 │ ├── icon.svg │ └── manifest.json ├── postcss.config.js ├── lib │ ├── constants │ │ ├── index.ts │ │ ├── devices.ts │ │ ├── browsers.ts │ │ └── metrics.ts │ ├── config.ts │ ├── types │ │ └── api.ts │ ├── hooks │ │ ├── use-domains.ts │ │ ├── use-auth.ts │ │ ├── use-current-visitors.ts │ │ ├── use-endpoint.ts │ │ ├── use-domain.ts │ │ └── use-time-range.ts │ ├── types.ts │ ├── utils.ts │ └── api.ts ├── .prettierrc ├── components │ ├── ui │ │ ├── Link.module.css │ │ ├── SqlChart.module.css │ │ ├── Input.tsx │ │ ├── Link.tsx │ │ ├── Tooltip.module.css │ │ ├── Textarea.tsx │ │ ├── Skeleton.tsx │ │ ├── Textarea.module.css │ │ ├── Loader.module.css │ │ ├── Badge.module.css │ │ ├── Stack.tsx │ │ ├── TimeRangeSelect.tsx │ │ ├── Dialog.module.css │ │ ├── Badge.tsx │ │ ├── Tooltip.tsx │ │ ├── Loader.tsx │ │ ├── Tabs.tsx │ │ ├── Button.tsx │ │ ├── DomainSelect.tsx │ │ ├── Tabs.module.css │ │ ├── Dialog.tsx │ │ ├── Input.module.css │ │ ├── Select.module.css │ │ ├── Text.module.css │ │ ├── Chart.module.css │ │ ├── Button.module.css │ │ └── Text.tsx │ ├── ai-chat │ │ ├── index.ts │ │ ├── AIChatStandalone.tsx │ │ ├── example-usage.tsx │ │ ├── AIChatProvider.tsx │ │ ├── AIChatToolCall.tsx │ │ ├── README.md │ │ ├── AIChatContainer.tsx │ │ ├── AIChatForm.tsx │ │ └── InsightCards.tsx │ ├── table │ │ ├── TableCells.module.css │ │ └── TableCells.tsx │ ├── Provider.tsx │ └── Header.tsx ├── mocks │ ├── server.ts │ └── handlers.ts ├── .vscode │ └── settings.json ├── assets │ └── fonts │ │ └── iawritermonos-regular.woff2 ├── .env.example ├── next.config.js ├── app │ ├── widgets │ │ ├── index.tsx │ │ ├── visitors.tsx │ │ ├── pageviews.tsx │ │ ├── top-browsers.tsx │ │ ├── top-devices.tsx │ │ ├── top-pages.tsx │ │ ├── top-sources.tsx │ │ └── top-locations.tsx │ ├── DashboardTabs.tsx │ └── layout.tsx ├── .eslintrc.js ├── .gitignore ├── styles │ └── theme │ │ └── index.js ├── tailwind.config.js ├── tsconfig.json ├── package.json └── README.md ├── CONTRIBUTING.md ├── .github └── workflows │ ├── release-workflow.yml │ ├── tinybird-ci.yml │ └── ci-workflow.yml ├── LICENSE ├── TEMPLATE.md ├── CHANGELOG.md └── CODE_OF_CONDUCT.md /tinybird/.env.local: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tinybird/.gitignore: -------------------------------------------------------------------------------- 1 | .tinyb 2 | .terraform 3 | -------------------------------------------------------------------------------- /middleware/.vercelignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .parcel-cache 4 | -------------------------------------------------------------------------------- /middleware/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | node_modules 3 | dist 4 | .parcel-cache 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .venv 3 | .tinyb 4 | .vercel 5 | node_modules 6 | dist 7 | .e 8 | .env 9 | tmp/ -------------------------------------------------------------------------------- /dashboard-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard-template.png -------------------------------------------------------------------------------- /assets/img/data_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/assets/img/data_flow.png -------------------------------------------------------------------------------- /assets/img/repo-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/assets/img/repo-banner.png -------------------------------------------------------------------------------- /dashboard/public/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/public/banner.png -------------------------------------------------------------------------------- /dashboard/public/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/public/chart.png -------------------------------------------------------------------------------- /dashboard/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/public/favicon.ico -------------------------------------------------------------------------------- /assets/img/banner_snippet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/assets/img/banner_snippet.png -------------------------------------------------------------------------------- /assets/img/events-incoming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/assets/img/events-incoming.png -------------------------------------------------------------------------------- /dashboard/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /assets/img/banner_dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/assets/img/banner_dashboard.png -------------------------------------------------------------------------------- /dashboard/public/fallback-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/public/fallback-logo.png -------------------------------------------------------------------------------- /dashboard/lib/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './metrics' 2 | export * from './countries' 3 | export * from './browsers' 4 | export * from './devices' -------------------------------------------------------------------------------- /dashboard/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "useTabs": false, 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /dashboard/components/ui/Link.module.css: -------------------------------------------------------------------------------- 1 | .link { 2 | color: var(--alternative-color); 3 | 4 | &:hover { 5 | text-decoration: underline; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /dashboard/mocks/server.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | 4 | export const server = setupServer(...handlers) 5 | -------------------------------------------------------------------------------- /dashboard/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.workingDirectories": [ 3 | { 4 | "directory": "./", 5 | "changeProcessCWD": true 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /dashboard/assets/fonts/iawritermonos-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/assets/fonts/iawritermonos-regular.woff2 -------------------------------------------------------------------------------- /dashboard/public/fonts/Inter-roman-latin.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinybirdco/web-analytics-starter-kit/HEAD/dashboard/public/fonts/Inter-roman-latin.var.woff2 -------------------------------------------------------------------------------- /middleware/.npmignore: -------------------------------------------------------------------------------- 1 | #.npmignore 2 | src 3 | test 4 | CHANGELOG.md 5 | .parcel-cache 6 | .vercel 7 | node_modules 8 | .eslintrc 9 | .babelrc 10 | examples 11 | .vercelignore 12 | -------------------------------------------------------------------------------- /dashboard/lib/constants/devices.ts: -------------------------------------------------------------------------------- 1 | const devices = { 2 | desktop: 'Desktop', 3 | 'mobile-android': 'Android', 4 | 'mobile-ios': 'iOS', 5 | bot: 'Bots', 6 | } 7 | 8 | export default devices 9 | -------------------------------------------------------------------------------- /dashboard/lib/constants/browsers.ts: -------------------------------------------------------------------------------- 1 | const browsers = { 2 | chrome: 'Chrome', 3 | safari: 'Safari', 4 | opera: 'Opera', 5 | firefox: 'Firefox', 6 | ie: 'IE', 7 | } 8 | 9 | export default browsers 10 | -------------------------------------------------------------------------------- /dashboard/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_ASK_TINYBIRD_ENDPOINT="https://ask-tb.tinybird.live/api/chat" 2 | 3 | NEXT_PUBLIC_TINYBIRD_DASHBOARD_URL=http://localhost:3000 4 | NEXT_PUBLIC_TINYBIRD_TRACKER_TOKEN= 5 | NEXT_PUBLIC_TINYBIRD_AUTH_TOKEN= 6 | NEXT_PUBLIC_TINYBIRD_HOST= -------------------------------------------------------------------------------- /dashboard/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | swcMinify: true, 5 | i18n: { 6 | locales: ['en'], 7 | defaultLocale: 'en', 8 | }, 9 | } 10 | 11 | module.exports = nextConfig 12 | -------------------------------------------------------------------------------- /dashboard/components/ui/SqlChart.module.css: -------------------------------------------------------------------------------- 1 | .sqlChartCard { 2 | min-width: 240px; 3 | flex: 1; 4 | border-radius: 4px; 5 | transition: border-color 0.2s ease-in-out; 6 | } 7 | 8 | .sqlChartCard.clickable:hover { 9 | border-color: var(--border-03-color); 10 | } -------------------------------------------------------------------------------- /middleware/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

If you are not redirected, click here.

8 | 9 | 10 | -------------------------------------------------------------------------------- /dashboard/components/ui/Input.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import * as React from 'react' 3 | import styles from './Input.module.css' 4 | import { cn } from '@/lib/utils' 5 | 6 | export function Input({ className, ...props }: React.ComponentProps<'input'>) { 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /dashboard/app/widgets/index.tsx: -------------------------------------------------------------------------------- 1 | export { Visitors } from './visitors' 2 | export { Pageviews } from './pageviews' 3 | export { TopPages } from './top-pages' 4 | export { TopLocations } from './top-locations' 5 | export { TopSources } from './top-sources' 6 | export { TopDevices } from './top-devices' 7 | export { TopBrowsers } from './top-browsers' -------------------------------------------------------------------------------- /dashboard/components/ai-chat/index.ts: -------------------------------------------------------------------------------- 1 | export { AIChatProvider, useAIChat } from './AIChatProvider' 2 | export { AIChatForm } from './AIChatForm' 3 | export { AIChatMessage } from './AIChatMessage' 4 | export { AIChatToolCall } from './AIChatToolCall' 5 | export { AIChatContainer } from './AIChatContainer' 6 | export { AIChatStandalone } from './AIChatStandalone' -------------------------------------------------------------------------------- /dashboard/lib/config.ts: -------------------------------------------------------------------------------- 1 | const config = { 2 | dashboardURL: process.env.NEXT_PUBLIC_TINYBIRD_DASHBOARD_URL as string, 3 | trackerToken: process.env.NEXT_PUBLIC_TINYBIRD_TRACKER_TOKEN as string, 4 | authToken: process.env.NEXT_PUBLIC_TINYBIRD_AUTH_TOKEN as string, 5 | host: process.env.NEXT_PUBLIC_TINYBIRD_HOST as string, 6 | tenantId: process.env.TENANT_ID as string, 7 | } as const 8 | 9 | export default config 10 | -------------------------------------------------------------------------------- /dashboard/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('eslint').Linter.Config} 3 | */ 4 | module.exports = { 5 | extends: ['next/core-web-vitals', 'prettier'], 6 | plugins: ['prettier'], 7 | ignorePatterns: ['node_modules', 'dist'], 8 | parserOptions: { 9 | babelOptions: { 10 | presets: [require.resolve('next/babel')], 11 | }, 12 | }, 13 | rules: { 14 | '@next/next/no-img-element': 'off', 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /dashboard/components/ui/Link.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils' 2 | import NextLink from 'next/link' 3 | import type { ComponentProps } from 'react' 4 | import styles from './Link.module.css' 5 | 6 | type LinkProps = ComponentProps & { 7 | className?: string 8 | } 9 | 10 | export function Link({ className, ...props }: LinkProps) { 11 | return 12 | } 13 | -------------------------------------------------------------------------------- /dashboard/public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dashboard/components/ui/Tooltip.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | z-index: 50; 3 | overflow: hidden; 4 | border-radius: 4px; 5 | background-color: var(--background-dark-color); 6 | box-shadow: 0 3px 7px rgb(0 0 0 / 13%), 0 0.6px 2px rgb(0 0 0 / 10%); 7 | padding: 4px 8px; 8 | font: var(--font-caption); 9 | color: var(--text-inverse-color); 10 | } 11 | 12 | .content.light { 13 | background-color: var(--background-color); 14 | color: var(--text-color); 15 | } -------------------------------------------------------------------------------- /tinybird/datasources/analytics_pages_mv.datasource: -------------------------------------------------------------------------------- 1 | SCHEMA > 2 | `date` Date, 3 | `tenant_id` String, 4 | `domain` String, 5 | `device` String, 6 | `browser` String, 7 | `location` String, 8 | `pathname` String, 9 | `visits` AggregateFunction(uniq, String), 10 | `hits` AggregateFunction(count) 11 | 12 | ENGINE AggregatingMergeTree 13 | ENGINE_PARTITION_KEY toYYYYMM(date) 14 | ENGINE_SORTING_KEY tenant_id, domain, date, device, browser, location, pathname -------------------------------------------------------------------------------- /dashboard/components/ui/Textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { cn } from '@/lib/utils' 4 | import styles from './Textarea.module.css' 5 | 6 | const Textarea = React.forwardRef< 7 | HTMLTextAreaElement, 8 | React.ComponentPropsWithoutRef<'textarea'> 9 | >(({ className, ...props }, ref) => { 10 | return