diff --git a/.github/workflows/template-build-linux-x64.yml b/.github/workflows/template-build-linux-x64.yml
index 9d12c4394..85b050e62 100644
--- a/.github/workflows/template-build-linux-x64.yml
+++ b/.github/workflows/template-build-linux-x64.yml
@@ -103,7 +103,7 @@ jobs:
# check public_provider is true or not
echo "public_provider is ${{ inputs.public_provider }}"
if [ "${{ inputs.public_provider }}" == "none" ]; then
- make build
+ make build
else
make build-and-publish
fi
@@ -122,8 +122,6 @@ jobs:
make build-and-publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
- ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
diff --git a/.github/workflows/template-build-macos.yml b/.github/workflows/template-build-macos.yml
index b415d665d..2eabd9ce2 100644
--- a/.github/workflows/template-build-macos.yml
+++ b/.github/workflows/template-build-macos.yml
@@ -134,7 +134,7 @@ jobs:
# check public_provider is true or not
echo "public_provider is ${{ inputs.public_provider }}"
if [ "${{ inputs.public_provider }}" == "none" ]; then
- make build
+ make build
else
make build-and-publish
fi
@@ -168,8 +168,6 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APP_PATH: '.'
DEVELOPER_ID: ${{ secrets.DEVELOPER_ID }}
- ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
- ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
POSTHOG_HOST: ${{ secrets.POSTHOG_HOST }}
diff --git a/.github/workflows/template-build-windows-x64.yml b/.github/workflows/template-build-windows-x64.yml
index 52ff22ce3..a317b4960 100644
--- a/.github/workflows/template-build-windows-x64.yml
+++ b/.github/workflows/template-build-windows-x64.yml
@@ -136,7 +136,7 @@ jobs:
# check public_provider is true or not
echo "public_provider is ${{ inputs.public_provider }}"
if [ "${{ inputs.public_provider }}" == "none" ]; then
- make build
+ make build
else
make build-and-publish
fi
@@ -160,8 +160,6 @@ jobs:
make build-and-publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
- ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}
AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
diff --git a/docs/src/pages/about/handbook/analytics.mdx b/docs/src/pages/about/handbook/analytics.mdx
index 9e7833e32..5cc34209d 100644
--- a/docs/src/pages/about/handbook/analytics.mdx
+++ b/docs/src/pages/about/handbook/analytics.mdx
@@ -23,6 +23,4 @@ Adhering to Jan's privacy preserving philosophy, our analytics philosophy is to
## What is tracked
1. By default, Github tracks downloads and device metadata for all public GitHub repositories. This helps us troubleshoot & ensure cross-platform support.
-2. We use [Umami](https://umami.is/) to collect, analyze, and understand application data while maintaining visitor privacy and data ownership. We are using the Umami Cloud in Europe to ensure GDPR compliance. Please see [Umami Privacy Policy](https://umami.is/privacy) for more details.
-3. We use Umami to track a single `app.opened` event without additional user metadata, in order to understand retention. In addition, we track `app.version` to understand app version usage.
-4. Additionally, we plan to enable a `Settings` feature for users to turn off all tracking.
+2. Additionally, we plan to enable a `Settings` feature for users to turn off all tracking.
diff --git a/docs/src/pages/privacy.mdx b/docs/src/pages/privacy.mdx
index bb77327e6..44127a37a 100644
--- a/docs/src/pages/privacy.mdx
+++ b/docs/src/pages/privacy.mdx
@@ -10,27 +10,20 @@ Homebrew Computer Company is committed to protecting your privacy and ensuring t
## Data Collection
-Jan, Cortex, and all Homebrew Computer Company products do not collect personally identifying information. You can read about [our philosophy](/about#philosophy) here and audit our open-source codebases.
+Jan, Cortex, and all Homebrew Computer Company products do not collect personally identifying information. You can read about [our philosophy](/about#philosophy) here and audit our open-source codebases.
### When you voluntarily provide data
-We -do- collect personal information you voluntarily provide us, e.g., when you sign up for our newsletter, join our Discord, or contact us via email.
+We -do- collect personal information you voluntarily provide us, e.g., when you sign up for our newsletter, join our Discord, or contact us via email.
-### Jan
+### Jan
-Jan runs with privacy by default and is used 100% offline on your own computer. Your data (e.g., conversation history, usage logs) are stored locally and never leave your computer.
+Jan runs with privacy by default and is used 100% offline on your own computer. Your data (e.g., conversation history, usage logs) are stored locally and never leave your computer.
If you use a Remote AI API (e.g., OpenAI API, Groq API), your data will naturally travel to their servers. They will be subject to the privacy policy of the respective API provider.
-Jan uses [Umami](https://umami.is/) for analytics, which is a privacy-focused, GDPR-compliant analytics tool that does not track personal information. We use this to get aggregate reports on OS and hardware types and prioritize our engineering roadmap. As per [Umami's Privacy Policy](https://umami.is/privacy), Umami uses the following data points to generate its reports:
-
-- OS and device characteristics
-- IP address
-
-Jan does not get any of this data, and we do not track IP addresses or other identifying information. We are actively looking into more privacy-respecting ways to handle analytics, crash reports, and telemetry and would love to work with the community on this.
-
### Cortex
Cortex is a library that runs large language models (LLMs) locally on your computer. Cortex does not collect any personal information.
diff --git a/web/containers/Providers/index.tsx b/web/containers/Providers/index.tsx
index 84e0860ea..5d14ea95a 100644
--- a/web/containers/Providers/index.tsx
+++ b/web/containers/Providers/index.tsx
@@ -9,8 +9,6 @@ import JotaiWrapper from '@/containers/Providers/Jotai'
import ThemeWrapper from '@/containers/Providers/Theme'
-import Umami from '@/utils/umami'
-
import { CoreConfigurator } from './CoreConfigurator'
import DataLoader from './DataLoader'
@@ -26,7 +24,6 @@ const Providers = ({ children }: PropsWithChildren) => {
-
<>
diff --git a/web/public/umami_script.js b/web/public/umami_script.js
deleted file mode 100644
index b9db0b024..000000000
--- a/web/public/umami_script.js
+++ /dev/null
@@ -1,210 +0,0 @@
-!(function () {
- 'use strict'
- !(function (t) {
- var e = t.screen,
- n = e.width,
- r = e.height,
- a = t.navigator.language,
- i = t.location,
- o = t.localStorage,
- u = t.document,
- c = t.history,
- f = 'jan.ai',
- s = 'mainpage',
- l = i.search,
- d = u.currentScript
- if (d) {
- var m = 'data-',
- h = d.getAttribute.bind(d),
- v = h(m + 'website-id'),
- p = h(m + 'host-url'),
- g = 'false' !== h(m + 'auto-track'),
- y = h(m + 'do-not-track'),
- b = h(m + 'domains') || '',
- S = b.split(',').map(function (t) {
- return t.trim()
- }),
- k =
- (p ? p.replace(/\/$/, '') : d.src.split('/').slice(0, -1).join('/')) +
- '/api/send',
- w = n + 'x' + r,
- N = /data-umami-event-([\w-_]+)/,
- T = m + 'umami-event',
- j = 300,
- A = function (t, e, n) {
- var r = t[e]
- return function () {
- for (var e = [], a = arguments.length; a--; ) e[a] = arguments[a]
- return n.apply(null, e), r.apply(t, e)
- }
- },
- x = function () {
- return {
- website: v,
- hostname: f,
- screen: w,
- language: a,
- title: M,
- url: I,
- referrer: J,
- }
- },
- E = function () {
- return (
- (o && o.getItem('umami.disabled')) ||
- (y &&
- (function () {
- var e = t.doNotTrack,
- n = t.navigator,
- r = t.external,
- a = 'msTrackingProtectionEnabled',
- i =
- e ||
- n.doNotTrack ||
- n.msDoNotTrack ||
- (r && a in r && r[a]())
- return '1' == i || 'yes' === i
- })()) ||
- (b && !S.includes(f))
- )
- },
- O = function (t, e, n) {
- n &&
- ((J = I),
- (I = (function (t) {
- try {
- return new URL(t).pathname
- } catch (e) {
- return t
- }
- })(n.toString())) !== J && setTimeout(D, j))
- },
- L = function (t, e) {
- if ((void 0 === e && (e = 'event'), !E())) {
- var n = {
- // eslint-disable-next-line @typescript-eslint/naming-convention
- 'Content-Type': 'application/json',
- }
- return (
- void 0 !== K && (n['x-umami-cache'] = K),
- fetch(k, {
- method: 'POST',
- body: JSON.stringify({
- type: e,
- payload: t,
- }),
- headers: n,
- })
- .then(function (t) {
- return t.text()
- })
- .then(function (t) {
- return (K = t)
- })
- .catch(function () {})
- )
- }
- },
- D = function (t, e) {
- return L(
- 'string' == typeof t
- ? Object.assign({}, x(), {
- name: t,
- data: 'object' == typeof e ? e : void 0,
- })
- : 'object' == typeof t
- ? t
- : 'function' == typeof t
- ? t(x())
- : x()
- )
- }
- t.umami ||
- (t.umami = {
- track: D,
- identify: function (t) {
- return L(
- Object.assign({}, x(), {
- data: t,
- }),
- 'identify'
- )
- },
- })
- var K,
- P,
- _,
- q,
- C,
- I = '' + s + l,
- J = u.referrer,
- M = u.title
- if (g && !E()) {
- ;(c.pushState = A(c, 'pushState', O)),
- (c.replaceState = A(c, 'replaceState', O)),
- (C = function (t) {
- var e = t.getAttribute.bind(t),
- n = e(T)
- if (n) {
- var r = {}
- return (
- t.getAttributeNames().forEach(function (t) {
- var n = t.match(N)
- n && (r[n[1]] = e(t))
- }),
- D(n, r)
- )
- }
- return Promise.resolve()
- }),
- u.addEventListener(
- 'click',
- function (t) {
- var e = t.target,
- n =
- 'A' === e.tagName
- ? e
- : (function (t, e) {
- for (var n = t, r = 0; r < e; r++) {
- if ('A' === n.tagName) return n
- if (!(n = n.parentElement)) return null
- }
- return null
- })(e, 10)
- if (n) {
- var r = n.href,
- a =
- '_blank' === n.target ||
- t.ctrlKey ||
- t.shiftKey ||
- t.metaKey ||
- (t.button && 1 === t.button)
- if (n.getAttribute(T) && r)
- return (
- a || t.preventDefault(),
- C(n).then(function () {
- a || (i.href = r)
- })
- )
- } else C(e)
- },
- !0
- ),
- (_ = new MutationObserver(function (t) {
- var e = t[0]
- M = e && e.target ? e.target.text : void 0
- })),
- (q = u.querySelector('head > title')) &&
- _.observe(q, {
- subtree: !0,
- characterData: !0,
- childList: !0,
- })
- var R = function () {
- 'complete' !== u.readyState || P || (D(), (P = !0))
- }
- u.addEventListener('readystatechange', R, !0), R()
- }
- }
- })(window)
-})()
diff --git a/web/utils/umami.tsx b/web/utils/umami.tsx
deleted file mode 100644
index dc406a7d2..000000000
--- a/web/utils/umami.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { useEffect } from 'react'
-
-import Script from 'next/script'
-
-// Define the type for the umami data object
-interface UmamiData {
- version: string
-}
-
-declare global {
- interface Window {
- umami:
- | {
- track: (event: string, data?: UmamiData) => void
- }
- | undefined
- }
-}
-
-const Umami = () => {
- const appVersion = VERSION
- const analyticsScriptPath = './umami_script.js'
- const analyticsId = ANALYTICS_ID
-
- useEffect(() => {
- if (!appVersion || !analyticsScriptPath || !analyticsId) return
-
- const ping = () => {
- // Check if umami is defined before ping
- if (window.umami !== null && typeof window.umami !== 'undefined') {
- window.umami.track(appVersion, {
- version: appVersion,
- })
- }
- }
-
- // Wait for umami to be defined before ping
- if (window.umami !== null && typeof window.umami !== 'undefined') {
- ping()
- } else {
- // Listen for umami script load event
- document.addEventListener('umami:loaded', ping)
- }
-
- // Cleanup function to remove event listener if the component unmounts
- return () => {
- document.removeEventListener('umami:loaded', ping)
- }
- }, [appVersion, analyticsScriptPath, analyticsId])
-
- return (
- <>
- {appVersion && analyticsScriptPath && analyticsId && (
-