Skip to content

Commit

Permalink
✨ feat: add several analytics sdk (#244)
Browse files Browse the repository at this point in the history
* 🚧 wip: add analytics env

* ✨ feat: add several analytics sdk

* 📝 docs: update document
  • Loading branch information
arvinxx authored Sep 27, 2023
1 parent c5c8e90 commit 65c6c93
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 15 deletions.
19 changes: 19 additions & 0 deletions docs/Analytics.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 数据统计

为更好地帮助分析 LobeChat 的用户使用情况,我们在 LobeChat 中集成了若干免费 / 开源的数据统计服务,用于收集用户的使用情况,你可以按需开启。

## Vercel Analytics

[Vercel Analytics](https://vercel.com/analytics) 是 Vercel 推出的一款数据分析服务,它可以帮助你收集网站的访问情况,包括访问量、访问来源、访问设备等等。

由于我们推荐使用 Vercel 一键部署 LobeChat,因此我们在代码中默认集成了 Vercel Analytics,你可以通过自行打开部署项目中 \[Insights] tab,查看你的应用访问情况。

Vercel Analytics 提供了 2500 次 / 月的免费 Web Analytics Events (可以理解为 PV),对于个人部署自用的产品来说基本够用。

如果你需要了解 Vercel Analytics 的详细使用教程,请查阅[Vercel Web Analytics 快速开始](https://vercel.com/docs/analytics/quickstart)

如果你不需要 Vercel Analytics,你可以通过设置环境变量 `NEXT_PUBLIC_ANALYTICS_VERCEL=0` 来关闭它。

## 🚧 Posthog

## 🚧 Mixpanel
81 changes: 80 additions & 1 deletion docs/Environment-Variable.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
- [`PLUGINS_INDEX_URL`](#plugins_index_url)
- [角色服务](#角色服务)
- [`AGENTS_INDEX_URL`](#agents_index_url)
- [数据统计](#数据统计)
- [Vercel Analytics](#vercel-analytics)
- [Mixpanel Analytics](#mixpanel-analytics)
- [`NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN`](#next_public_mixpanel_project_token)
- [`NEXT_PUBLIC_MIXPANEL_DEBUG`](#next_public_mixpanel_debug)
- [Posthog Analytics](#posthog-analytics)
- [`NEXT_PUBLIC_POSTHOG_DEBUG`](#next_public_posthog_debug)
- [开发环境](#开发环境)
- [`DEV_API_END_PORT_URL`](#dev_api_end_port_url)

Expand Down Expand Up @@ -94,7 +101,76 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
- 描述:LobeChat 角色市场的索引地址,如果你自行部署了角色市场的服务,可以使用该变量来覆盖默认的插件市场地址
- 默认值:`https://chat-agents.lobehub.com`

<br/>
## 数据统计

### Vercel Analytics

#### `NEXT_PUBLIC_ANALYTICS_VERCEL`

- 类型:可选
- 描述:用于配置 Vercel Analytics 的环境变量,当设为 `0` 则关闭 Vercel Analytics
- 默认值: -
- 示例:`0`

#### `NEXT_PUBLIC_VERCEL_DEBUG`

- 类型:可选
- 描述:用于开启 Vercel Analytics 的调试模式
- 默认值: -
- 示例:`1`

### Mixpanel Analytics

#### `NEXT_PUBLIC_ANALYTICS_MIXPANEL`

- 类型:可选
- 描述:用于开启 [Mixpanel Analytics][mixpanel-analytics-url] 的环境变量,设为 `1` 时开启 Mixpanel Analytics
- 默认值: -
- 示例:`1`

### `NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN`

- 类型:可选
- 描述:设置 Mixpanel 项目的识别 Token,可以在[这里][mixpanel-project-url]找到
- 默认值: -
- 示例:`60db2abae7fdd29961f4e8f91b074b3a`

### `NEXT_PUBLIC_MIXPANEL_DEBUG`

- 类型:可选
- 描述:开启 Mixpanel 的调试模式
- 默认值: -
- 示例:`1`

### Posthog Analytics

#### `NEXT_PUBLIC_ANALYTICS_POSTHOG`

- 类型:可选
- 描述:用于开启 [PostHog Analytics][posthog-analytics-url] 的环境变量,设为 `1` 时开启 PostHog Analytics
- 默认值: -
- 示例:`1`

#### `NEXT_PUBLIC_POSTHOG_KEY`

- 类型:可选
- 描述:设置 PostHog 项目 Key
- 默认值: -
- 示例:`phc_xxxxxxxx`

#### `NEXT_PUBLIC_POSTHOG_HOST`

- 类型:可选
- 描述:设置 PostHog 服务的部署地址,默认为官方的 SAAS 地址
- 默认值:`https://app.posthog.com`
- 示例:`https://example.com`

### `NEXT_PUBLIC_POSTHOG_DEBUG`

- 类型:可选
- 描述:开启 PostHog 的调试模式
- 默认值: -
- 示例:`1`

## 开发环境

Expand All @@ -106,4 +182,7 @@ LobeChat 在部署时提供了一些额外的配置项,使用环境变量进
- 示例:`https://chat-preview.lobehub.com`

[azure-api-verion-url]: https://docs.microsoft.com/zh-cn/azure/developer/javascript/api-reference/es-modules/azure-sdk/ai-translation/translationconfiguration?view=azure-node-latest#api-version
[mixpanel-analytics-url]: https://mixpanel.com
[mixpanel-project-url]: https://mixpanel.com/settings/project
[openai-api-page]: https://platform.openai.com/account/api-keys
[posthog-analytics-url]: https://posthog.com
4 changes: 4 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const nextConfig = {
},
];
},
env: {
AGENTS_INDEX_URL: process.env.AGENTS_INDEX_URL,
PLUGINS_INDEX_URL: process.env.PLUGINS_INDEX_URL,
},
};

export default isProd ? withPWA(nextConfig) : nextConfig;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@
"immer": "^10",
"lodash-es": "^4",
"lucide-react": "latest",
"mixpanel-browser": "^2",
"nanoid": "^5",
"next": "^13.5.3",
"openai": "^4",
"polished": "^4",
"posthog-js": "^1",
"react": "^18",
"react-dom": "^18",
"react-hotkeys-hook": "^4",
Expand All @@ -116,6 +118,7 @@
"@testing-library/react": "^14",
"@types/chroma-js": "^2",
"@types/lodash-es": "^4",
"@types/mixpanel-browser": "^2",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
23 changes: 23 additions & 0 deletions src/components/Analytics/Mixpanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import mixpanel from 'mixpanel-browser';
import { memo, useEffect } from 'react';

import { getClientConfig } from '@/config/client';

const { MIXPANEL_PROJECT_TOKEN, MIXPANEL_DEBUG } = getClientConfig();

const MixpanelAnalytics = memo(() => {
useEffect(() => {
if (!MIXPANEL_PROJECT_TOKEN) return;

mixpanel.init(MIXPANEL_PROJECT_TOKEN, {
debug: MIXPANEL_DEBUG,
persistence: 'localStorage',
track_pageview: true,
});
}, []);
return null;
});

export default MixpanelAnalytics;
18 changes: 18 additions & 0 deletions src/components/Analytics/Plausible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client';

import Script from 'next/script';
import { memo } from 'react';

import { getClientConfig } from '@/config/client';

const { PLAUSIBLE_DOMAIN } = getClientConfig();

const PlausibleAnalytics = memo(() => {
return (
PLAUSIBLE_DOMAIN && (
<Script data-domain={PLAUSIBLE_DOMAIN} defer src="https://plausible.io/js/script.js" />
)
);
});

export default PlausibleAnalytics;
23 changes: 23 additions & 0 deletions src/components/Analytics/Posthog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import posthog from 'posthog-js';
import { FC, memo, useEffect } from 'react';

import { getClientConfig } from '@/config/client';

const { POSTHOG_HOST, POSTHOG_KEY, POSTHOG_DEBUG } = getClientConfig();

const PostHog: FC = memo(() => {
useEffect(() => {
if (!POSTHOG_KEY) return;

posthog.init(POSTHOG_KEY, {
api_host: POSTHOG_HOST ?? 'https://app.posthog.com',
debug: POSTHOG_DEBUG,
});
}, []);

return null;
});

export default PostHog;
12 changes: 12 additions & 0 deletions src/components/Analytics/Vercel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import { Analytics } from '@vercel/analytics/react';
import { memo } from 'react';

import { getClientConfig } from '@/config/client';

const { VERCEL_DEBUG } = getClientConfig();

const VercelAnalytics = memo(() => <Analytics debug={VERCEL_DEBUG} />);

export default VercelAnalytics;
21 changes: 19 additions & 2 deletions src/components/Analytics/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import { Analytics as VercelAnalytics } from '@vercel/analytics/react';
import dynamic from 'next/dynamic';

import { getClientConfig } from '@/config/client';

const Vercel = dynamic(() => import('./Vercel'), { ssr: false });
const Mixpanel = dynamic(() => import('./Mixpanel'), { ssr: false });
const Plausible = dynamic(() => import('./Plausible'), { ssr: false });
const Posthog = dynamic(() => import('./Posthog'), { ssr: false });

const { ANALYTICS_VERCEL, ANALYTICS_POSTHOG, ANALYTICS_MIXPANEL, ANALYTICS_PLAUSIBLE } =
getClientConfig();

const Analytics = () => {
return <VercelAnalytics />;
return (
<>
{ANALYTICS_VERCEL && <Vercel />}
{ANALYTICS_PLAUSIBLE && <Plausible />}
{ANALYTICS_MIXPANEL && <Mixpanel />}
{ANALYTICS_POSTHOG && <Posthog />}
</>
);
};

export default Analytics;
7 changes: 3 additions & 4 deletions src/components/AppTheme/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export interface AppThemeProps {

const AppTheme = memo<AppThemeProps>(
({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor }) => {
console.log('server:appearance', defaultAppearance);
console.log('server:primaryColor', defaultPrimaryColor);
console.log('server:neutralColor', defaultNeutralColor);
// console.log('server:appearance', defaultAppearance);
// console.log('server:primaryColor', defaultPrimaryColor);
// console.log('server:neutralColor', defaultNeutralColor);
const themeMode = useGlobalStore((s) => s.settings.themeMode);

const [primaryColor, neutralColor] = useGlobalStore((s) => [
Expand All @@ -31,7 +31,6 @@ const AppTheme = memo<AppThemeProps>(
]);

useEffect(() => {
console.log(primaryColor);
setCookie(LOBE_THEME_PRIMARY_COLOR, primaryColor);
}, [primaryColor]);

Expand Down
46 changes: 46 additions & 0 deletions src/config/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable sort-keys-fix/sort-keys-fix , typescript-sort-keys/interface */

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {
interface ProcessEnv {
AGENTS_INDEX_URL?: string;
PLUGINS_INDEX_URL?: string;

NEXT_PUBLIC_ANALYTICS_VERCEL?: string;
NEXT_PUBLIC_VERCEL_DEBUG?: string;

NEXT_PUBLIC_ANALYTICS_MIXPANEL?: string;
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN?: string;
NEXT_PUBLIC_MIXPANEL_DEBUG?: string;

NEXT_PUBLIC_ANALYTICS_PLAUSIBLE?: string;
NEXT_PUBLIC_PLAUSIBLE_DOMAIN?: string;

NEXT_PUBLIC_ANALYTICS_POSTHOG: string;
NEXT_PUBLIC_POSTHOG_KEY: string;
NEXT_PUBLIC_POSTHOG_HOST: string;
NEXT_PUBLIC_POSTHOG_DEBUG: string;
}
}
}

export const getClientConfig = () => ({
AGENTS_INDEX_URL: process.env.AGENTS_INDEX_URL,
PLUGINS_INDEX_URL: process.env.PLUGINS_INDEX_URL,

ANALYTICS_VERCEL: process.env.NEXT_PUBLIC_ANALYTICS_VERCEL !== '0',
VERCEL_DEBUG: process.env.NEXT_PUBLIC_VERCEL_DEBUG === '1',

ANALYTICS_PLAUSIBLE: process.env.NEXT_PUBLIC_ANALYTICS_PLAUSIBLE === '1',
PLAUSIBLE_DOMAIN: process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,

ANALYTICS_MIXPANEL: process.env.NEXT_PUBLIC_ANALYTICS_MIXPANEL === '1',
MIXPANEL_PROJECT_TOKEN: process.env.NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN,
MIXPANEL_DEBUG: process.env.NEXT_PUBLIC_MIXPANEL_DEBUG === '1',

ANALYTICS_POSTHOG: process.env.NEXT_PUBLIC_ANALYTICS_POSTHOG === '1',
POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
POSTHOG_DEBUG: process.env.NEXT_PUBLIC_POSTHOG_DEBUG === '1',
});
15 changes: 9 additions & 6 deletions src/config/server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/* eslint-disable sort-keys-fix/sort-keys-fix , typescript-sort-keys/interface */

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {
interface ProcessEnv {
ACCESS_CODE?: string;
AZURE_API_KEY?: string;
AZURE_API_VERSION?: string;

OPENAI_API_KEY?: string;
OPENAI_PROXY_URL?: string;

AZURE_API_KEY?: string;
AZURE_API_VERSION?: string;
USE_AZURE_OPENAI?: string;
}
}
Expand All @@ -19,13 +23,12 @@ export const getServerConfig = () => {

return {
ACCESS_CODE: process.env.ACCESS_CODE,
/* eslint-disable sort-keys-fix/sort-keys-fix */
AZURE_API_KEY: process.env.AZURE_API_KEY,
AZURE_API_VERSION: process.env.AZURE_API_VERSION,
/* eslint-enabled */

OPENAI_API_KEY: process.env.OPENAI_API_KEY,
OPENAI_PROXY_URL: process.env.OPENAI_PROXY_URL,

AZURE_API_KEY: process.env.AZURE_API_KEY,
AZURE_API_VERSION: process.env.AZURE_API_VERSION,
USE_AZURE_OPENAI: process.env.USE_AZURE_OPENAI === '1',
};
};
6 changes: 4 additions & 2 deletions src/const/url.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import urlJoin from 'url-join';

import { getClientConfig } from '@/config/client';
import { localeOptions } from '@/locales/options';
import { Locales } from '@/locales/resources';

Expand All @@ -13,7 +14,7 @@ export const FEEDBACK = pkg.bugs.url;
export const DISCORD = 'https://discord.gg/AYFPHvv2jT';

export const PLUGINS_INDEX_URL =
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com';
getClientConfig().PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com';

export const DEFAULT_LANG = 'en-US';

Expand All @@ -26,7 +27,8 @@ export const getPluginIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = PLUGI
return urlJoin(baseUrl, `index.${lang}.json`);
};

export const AGENTS_INDEX_URL = process.env.AGENTS_INDEX_URL ?? 'https://chat-agents.lobehub.com';
export const AGENTS_INDEX_URL =
getClientConfig().AGENTS_INDEX_URL ?? 'https://chat-agents.lobehub.com';

export const getAgentIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = AGENTS_INDEX_URL) => {
if (checkLang(lang)) return baseUrl;
Expand Down

0 comments on commit 65c6c93

Please sign in to comment.