diff --git a/app/config/config.server.ts b/app/config/config.server.ts
index 53e9ddd..7dab7f4 100644
--- a/app/config/config.server.ts
+++ b/app/config/config.server.ts
@@ -32,11 +32,7 @@ invariant(
typeof process.env.WEB_PUSH_VAPID_PUBLIC_KEY === "string",
`Please define the "WEB_PUSH_VAPID_PUBLIC_KEY" environment variable`,
);
-invariant(typeof process.env.SENTRY_DSN === "string", `Please define the "SENTRY_DSN" environment variable`);
-invariant(
- typeof process.env.PANELBEAR_SITE_ID === "string",
- `Please define the "PANELBEAR_SITE_ID" environment variable`,
-);
+invariant(typeof process.env.FATHOM_SITE_ID === "string", `Please define the "FATHOM_SITE_ID" environment variable`);
export default {
app: {
@@ -51,8 +47,9 @@ export default {
secretAccessKey: process.env.AWS_SES_ACCESS_KEY_SECRET,
fromEmail: process.env.AWS_SES_FROM_EMAIL,
},
- panelBear: {
- siteId: process.env.PANELBEAR_SITE_ID,
+ fathom: {
+ siteId: process.env.FATHOM_SITE_ID,
+ domain: process.env.FATHOM_CUSTOM_DOMAIN,
},
redis: {
url: process.env.REDIS_URL,
diff --git a/app/entry.client.tsx b/app/entry.client.tsx
index 4c7672c..1c3c82a 100644
--- a/app/entry.client.tsx
+++ b/app/entry.client.tsx
@@ -3,20 +3,14 @@ import { RemixBrowser } from "@remix-run/react";
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
-declare global {
- interface Window {
- shellphoneConfig: {
- sentry: { dsn: string };
- };
- }
+if (window.shellphoneConfig.sentry.dsn) {
+ Sentry.init({
+ dsn: window.shellphoneConfig.sentry.dsn,
+ tracesSampleRate: 1.0,
+ integrations: [new Integrations.BrowserTracing()],
+ });
}
-Sentry.init({
- dsn: window.shellphoneConfig.sentry.dsn,
- tracesSampleRate: 1.0,
- integrations: [new Integrations.BrowserTracing()],
-});
-
hydrate(, document);
if ("serviceWorker" in navigator) {
diff --git a/app/entry.worker.ts b/app/entry.worker.ts
index d7db2ed..a5e0a11 100644
--- a/app/entry.worker.ts
+++ b/app/entry.worker.ts
@@ -33,8 +33,8 @@ self.addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
const isSSERequest = event.request.headers.get("Accept") === "text/event-stream";
const isOutsideRequest = !["localhost", "dev.shellphone.app", "www.shellphone.app"].includes(url.hostname);
- const isSplitbeeProxiedRequest = url.pathname.startsWith("/_hive") || url.pathname === "/bee.js";
- if (isSSERequest || isOutsideRequest || isSplitbeeProxiedRequest) {
+
+ if (isSSERequest || isOutsideRequest) {
return;
}
diff --git a/app/features/core/hooks/use-fathom.ts b/app/features/core/hooks/use-fathom.ts
new file mode 100644
index 0000000..eb1b85b
--- /dev/null
+++ b/app/features/core/hooks/use-fathom.ts
@@ -0,0 +1,21 @@
+import { useEffect } from "react";
+import { useLocation } from "@remix-run/react";
+import * as Fathom from "fathom-client";
+
+export default function useFathom() {
+ const location = useLocation();
+
+ useEffect(() => {
+ const { fathom, app } = window.shellphoneConfig;
+ Fathom.load(fathom.siteId, {
+ spa: "history",
+ url: fathom.domain ? `https://${fathom.domain}/script.js` : undefined,
+ includedDomains: [app.baseUrl.replace("https://", "")],
+ });
+ }, []);
+
+ useEffect(() => {
+ console.log(`tracking ${location.pathname}`);
+ Fathom.trackPageview();
+ }, [location]);
+}
diff --git a/app/features/core/hooks/use-panelbear.ts b/app/features/core/hooks/use-panelbear.ts
deleted file mode 100644
index b4d50d9..0000000
--- a/app/features/core/hooks/use-panelbear.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useEffect } from "react";
-import { useLocation } from "@remix-run/react";
-import * as Panelbear from "@panelbear/panelbear-js";
-import type { PanelbearConfig } from "@panelbear/panelbear-js";
-
-export default function usePanelbear(siteId: string, config: PanelbearConfig = {}) {
- const location = useLocation();
-
- useEffect(() => {
- Panelbear.load(siteId, {
- scriptSrc: "/bear.js",
- spaMode: "off",
- autoTrack: false,
- ...config,
- });
- }, []);
-
- useEffect(() => {
- Panelbear.trackPageview();
- }, [location]);
-}
diff --git a/app/features/settings/actions/phone.ts b/app/features/settings/actions/phone.ts
index 7d027c9..87e06d4 100644
--- a/app/features/settings/actions/phone.ts
+++ b/app/features/settings/actions/phone.ts
@@ -145,6 +145,7 @@ async function setTwilioCredentials(request: Request, formData: unknown) {
await Promise.all(
phoneNumbers.map(async (phoneNumber) => {
const phoneNumberId = phoneNumber.sid;
+ logger.info(`Importing phone number with id=${phoneNumberId}`);
try {
await db.phoneNumber.create({
data: {
@@ -166,6 +167,8 @@ async function setTwilioCredentials(request: Request, formData: unknown) {
}),
]);
} catch (error: any) {
+ logger.error(error);
+
if (error.code !== "P2002") {
// if it's not a duplicate, it's a real error we need to handle
throw error;
diff --git a/app/root.tsx b/app/root.tsx
index 6d55d5a..8fcdadf 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -13,20 +13,30 @@ import {
} from "@remix-run/react";
import config from "~/config/config.server";
-import usePanelbear from "~/features/core/hooks/use-panelbear";
+import useFathom from "~/features/core/hooks/use-fathom";
import Logo from "~/features/core/components/logo";
import styles from "./styles/tailwind.css";
export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }];
+declare global {
+ interface Window {
+ shellphoneConfig: LoaderData["shellphoneConfig"];
+ }
+}
+
type LoaderData = {
shellphoneConfig: {
sentry: {
- dsn: string;
+ dsn?: string;
};
- panelbear: {
+ fathom: {
siteId: string;
+ domain?: string;
+ };
+ app: {
+ baseUrl: string;
};
};
};
@@ -36,8 +46,12 @@ export const loader: LoaderFunction = () => {
sentry: {
dsn: config.sentry.dsn,
},
- panelbear: {
- siteId: config.panelBear.siteId,
+ fathom: {
+ siteId: config.fathom.siteId,
+ domain: config.fathom.domain,
+ },
+ app: {
+ baseUrl: config.app.baseUrl,
},
},
});
@@ -45,7 +59,7 @@ export const loader: LoaderFunction = () => {
export default function App() {
const { shellphoneConfig } = useLoaderData();
- usePanelbear(shellphoneConfig.panelbear.siteId);
+ useFathom();
return (
@@ -136,7 +150,6 @@ const Document: FunctionComponent> = ({ children }) => (
{children}
-
diff --git a/app/routes/_hive.$.ts b/app/routes/_hive.$.ts
deleted file mode 100644
index 0078b10..0000000
--- a/app/routes/_hive.$.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { ActionFunction } from "remix";
-
-async function proxyHive(request: Request) {
- const url = new URL(request.url);
- const req = new Request("https://hive.splitbee.io" + url.pathname.replace("/_hive", ""), {
- ...request,
- signal: null,
- });
- req.headers.set("x-country", request.headers.get("cf-ipcountry")!);
- req.headers.set("x-real-ip", request.headers.get("x-real-ip")!);
- return fetch(req);
-}
-
-export const action: ActionFunction = ({ request }) => proxyHive(request);
diff --git a/app/routes/bear[.]js.ts b/app/routes/bear[.]js.ts
deleted file mode 100644
index d73b74f..0000000
--- a/app/routes/bear[.]js.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { LoaderFunction } from "remix";
-
-export const loader: LoaderFunction = () => fetch("https://cdn.panelbear.com/analytics.js");
diff --git a/app/routes/bee[.]js.ts b/app/routes/bee[.]js.ts
deleted file mode 100644
index b14709c..0000000
--- a/app/routes/bee[.]js.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { LoaderFunction } from "remix";
-
-export const loader: LoaderFunction = () => fetch("https://cdn.splitbee.io/sb.js");
diff --git a/package-lock.json b/package-lock.json
index dddfbb7..d272bb0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,6 @@
"@bull-board/express": "3.11.0",
"@headlessui/react": "1.6.4",
"@maizzle/framework": "3.7.3",
- "@panelbear/panelbear-js": "1.3.3",
"@prisma/client": "3.14.0",
"@react-aria/interactions": "3.9.0",
"@remix-run/express": "1.5.1",
@@ -28,6 +27,7 @@
"clsx": "1.1.1",
"compression": "1.7.4",
"express": "4.18.1",
+ "fathom-client": "3.5.0",
"ioredis": "5.0.6",
"isbot": "3.5.0",
"jotai": "1.7.0",
@@ -3027,11 +3027,6 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
- "node_modules/@panelbear/panelbear-js": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@panelbear/panelbear-js/-/panelbear-js-1.3.3.tgz",
- "integrity": "sha512-LsAxdlvdvyoQy04no/VsSMQd1i1qGFNMy328VG/BI5N5hQXIa8CZjCWNXuOjIMbJcltt7QjESMr6BgHuEeo5AA=="
- },
"node_modules/@prisma/client": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.14.0.tgz",
@@ -10270,6 +10265,11 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/fathom-client": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/fathom-client/-/fathom-client-3.5.0.tgz",
+ "integrity": "sha512-BiRDS9Q9a8Zma0H717FWC5cvf545K/CsxBpxKT22TcSl1EbRhhlHWIJgrdeiQUfdorBK2ppy09TwMOhRsbos/A=="
+ },
"node_modules/fault": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz",
@@ -24904,11 +24904,6 @@
"json-parse-even-better-errors": "^2.3.1"
}
},
- "@panelbear/panelbear-js": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@panelbear/panelbear-js/-/panelbear-js-1.3.3.tgz",
- "integrity": "sha512-LsAxdlvdvyoQy04no/VsSMQd1i1qGFNMy328VG/BI5N5hQXIa8CZjCWNXuOjIMbJcltt7QjESMr6BgHuEeo5AA=="
- },
"@prisma/client": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.14.0.tgz",
@@ -30300,6 +30295,11 @@
"reusify": "^1.0.4"
}
},
+ "fathom-client": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/fathom-client/-/fathom-client-3.5.0.tgz",
+ "integrity": "sha512-BiRDS9Q9a8Zma0H717FWC5cvf545K/CsxBpxKT22TcSl1EbRhhlHWIJgrdeiQUfdorBK2ppy09TwMOhRsbos/A=="
+ },
"fault": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz",
diff --git a/package.json b/package.json
index 0734b75..7792fc9 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,6 @@
"@bull-board/express": "3.11.0",
"@headlessui/react": "1.6.4",
"@maizzle/framework": "3.7.3",
- "@panelbear/panelbear-js": "1.3.3",
"@prisma/client": "3.14.0",
"@react-aria/interactions": "3.9.0",
"@remix-run/express": "1.5.1",
@@ -71,6 +70,7 @@
"clsx": "1.1.1",
"compression": "1.7.4",
"express": "4.18.1",
+ "fathom-client": "3.5.0",
"ioredis": "5.0.6",
"isbot": "3.5.0",
"jotai": "1.7.0",
diff --git a/server/index.ts b/server/index.ts
index e86c1b2..94d3bac 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -9,12 +9,14 @@ import logger from "~/utils/logger.server";
import { adminMiddleware, setupBullBoard } from "./queues";
import { registerSentry, sentryLoadContext } from "./sentry-remix";
-Sentry.init({
- dsn: config.sentry.dsn,
- integrations: [new Sentry.Integrations.Http({ tracing: true })],
- tracesSampleRate: 1.0,
- environment: process.env.NODE_ENV,
-});
+if (config.sentry.dsn) {
+ Sentry.init({
+ dsn: config.sentry.dsn,
+ integrations: [new Sentry.Integrations.Http({ tracing: true })],
+ tracesSampleRate: 1.0,
+ environment: process.env.NODE_ENV,
+ });
+}
const app = express();
app.use((req, res, next) => {