add posthog integration (#7)

* add possibility to track events with posthog by setting environment variables POSTHOG_API_KEY and POSTHOG_API_HOST
This commit is contained in:
Matthias Nannt
2022-07-22 16:15:39 +02:00
committed by GitHub
parent cb6b76c3e2
commit 277bd014ae
13 changed files with 372 additions and 259 deletions

View File

@@ -6,6 +6,7 @@ import { Fragment, useState } from "react";
import { BsPlus } from "react-icons/bs";
import { createForm } from "../../lib/forms";
import { createNoCodeForm } from "../../lib/noCodeForm";
import { trackPosthogEvent } from "../../lib/posthog";
import { classNames } from "../../lib/utils";
import StandardButton from "../StandardButton";
@@ -47,6 +48,7 @@ export default function NewFormModal({
if (form.formType === "NOCODE") {
await createNoCodeForm(form.id);
}
trackPosthogEvent("newForm", { formType: form.formType });
router.push(`/forms/${form.id}/form`);
};

View File

@@ -1,5 +1,6 @@
import { SnoopElement, SnoopForm, SnoopPage } from "@snoopforms/react";
import { useMemo } from "react";
import { trackPosthogEvent } from "../../lib/posthog";
import Loading from "../Loading";
export default function App({ id = "", formId, blocks, localOnly = false }) {
@@ -41,6 +42,9 @@ export default function App({ id = "", formId, blocks, localOnly = false }) {
formId={formId}
localOnly={localOnly}
className="w-full max-w-3xl mx-auto space-y-6"
onSubmit={() => {
trackPosthogEvent("submitForm", { formId });
}}
>
{pages.map((page) => (
<SnoopPage key={page.id} name={page.id}>

View File

@@ -1,6 +1,7 @@
import { signIn, useSession } from "next-auth/react";
import Head from "next/head";
import { useEffect, useState } from "react";
import { usePosthog } from "../../lib/posthog";
import { classNames } from "../../lib/utils";
import Loading from "../Loading";
import MenuBreadcrumbs from "./MenuBreadcrumbs";
@@ -40,6 +41,8 @@ export default function BaseLayoutAuthorized({
}
}, [session, status]);
usePosthog(session?.user?.email);
if (status === "loading" || loading) {
return <Loading />;
}

View File

@@ -0,0 +1,14 @@
import Head from "next/head";
import { usePosthog } from "../../lib/posthog";
export default function BaseLayoutUnauthorized({ title, children }) {
usePosthog(null, true);
return (
<>
<Head>
<title>{title}</title>
</Head>
{children}
</>
);
}

51
lib/posthog.ts Normal file
View File

@@ -0,0 +1,51 @@
import { useRouter } from "next/router";
import getConfig from "next/config";
import posthog from "posthog-js";
import { useEffect } from "react";
const { publicRuntimeConfig } = getConfig();
const enabled =
publicRuntimeConfig.posthogApiKey && publicRuntimeConfig.posthogApiHost;
export const usePosthog = (userId?: string, anonymous = false) => {
const router = useRouter();
useEffect(() => {
if (enabled && (userId || anonymous)) {
// Init PostHog
posthog.init(publicRuntimeConfig.posthogApiKey, {
api_host: publicRuntimeConfig.posthogApiHost,
loaded: function (posthog) {
if (process.env.NODE_ENV === "development")
posthog.opt_out_capturing();
if (userId && !anonymous) {
posthog.identify(userId);
}
},
});
}
// Track page views
const handleRouteChange = () => {
if (enabled && (userId || anonymous)) {
posthog.capture("$pageview");
}
};
router.events.on("routeChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}, [router.events, userId, anonymous]);
};
export const trackPosthogEvent = (eventName: string, attributes: object) => {
if (enabled) {
posthog.capture(eventName, attributes);
}
};
export const identifyPoshogUser = (userId: string) => {
if (enabled) {
posthog.identify(userId);
}
};

View File

@@ -16,6 +16,8 @@ const nextConfig = {
},
publicRuntimeConfig: {
// Will be available on both server and client
posthogApiHost: process.env.POSTHOG_API_HOST,
posthogApiKey: process.env.POSTHOG_API_KEY,
},
async redirects() {
return [

View File

@@ -28,6 +28,7 @@
"next-auth": "^4.10.1",
"nextjs-cors": "^2.1.1",
"nodemailer": "^6.7.7",
"posthog-js": "^1.26.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-icons": "^4.4.0",

View File

@@ -3,6 +3,7 @@ import { signIn } from "next-auth/react";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import BaseLayoutUnauthorized from "../../components/layout/BaseLayoutUnauthorized";
export default function SignInPage() {
const router = useRouter();
@@ -22,107 +23,109 @@ export default function SignInPage() {
);
};
return (
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
{error && (
<div className="absolute p-4 rounded-md top-10 bg-red-50">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon
className="w-5 h-5 text-red-400"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
An error occurred when logging you in
</h3>
<div className="mt-2 text-sm text-red-700">
<p className="space-y-1 whitespace-pre-wrap">{error}</p>
<BaseLayoutUnauthorized title="Sign in">
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
{error && (
<div className="absolute p-4 rounded-md top-10 bg-red-50">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon
className="w-5 h-5 text-red-400"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
An error occurred when logging you in
</h3>
<div className="mt-2 text-sm text-red-700">
<p className="space-y-1 whitespace-pre-wrap">{error}</p>
</div>
</div>
</div>
</div>
</div>
)}
)}
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<div className="mt-8">
<div className="mt-6">
<form
onSubmit={handleSubmit}
method="post"
action="/api/auth/callback/credentials"
className="space-y-6"
>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Email address
</label>
<div className="mt-1">
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div className="mt-8">
<div className="mt-6">
<form
onSubmit={handleSubmit}
method="post"
action="/api/auth/callback/credentials"
className="space-y-6"
>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Email address
</label>
<div className="mt-1">
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Password
</label>
<div className="mt-1">
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Password
</label>
<div className="mt-1">
<input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<button
type="submit"
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white border border-transparent rounded-md shadow-sm bg-red hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Sign in
</button>
<div className="mt-3 text-center">
<Link href="/auth/signup">
<a
href=""
className="text-xs text-red hover:text-red-600"
>
Create an account
</a>
</Link>
<div>
<button
type="submit"
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white border border-transparent rounded-md shadow-sm bg-red hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Sign in
</button>
<div className="mt-3 text-center">
<Link href="/auth/signup">
<a
href=""
className="text-xs text-red hover:text-red-600"
>
Create an account
</a>
</Link>
</div>
</div>
</div>
</form>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</BaseLayoutUnauthorized>
);
}

View File

@@ -3,6 +3,7 @@ import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { useState } from "react";
import BaseLayoutUnauthorized from "../../components/layout/BaseLayoutUnauthorized";
import { createUser } from "../../lib/users";
export default function SignUpPage() {
@@ -28,137 +29,139 @@ export default function SignUpPage() {
}
};
return (
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
{error && (
<div className="absolute p-4 rounded-md top-10 bg-red-50">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon
className="w-5 h-5 text-red-400"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
An error occurred when logging you in
</h3>
<div className="mt-2 text-sm text-red-700">
<p className="space-y-1 whitespace-pre-wrap">{error}</p>
<BaseLayoutUnauthorized title="Sign up">
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
{error && (
<div className="absolute p-4 rounded-md top-10 bg-red-50">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon
className="w-5 h-5 text-red-400"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
An error occurred when logging you in
</h3>
<div className="mt-2 text-sm text-red-700">
<p className="space-y-1 whitespace-pre-wrap">{error}</p>
</div>
</div>
</div>
</div>
</div>
)}
)}
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<div className="mt-8">
<p className="text-sm text-center text-gray-600">
Create your own forms and collect submissions by creating a
snoopForms account.
</p>
<div className="mt-6">
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label
htmlFor="firstname"
className="block text-sm font-medium text-ui-gray-dark"
>
First name
</label>
<div className="mt-1">
<input
id="firstname"
name="firstname"
type="text"
autoComplete="given-name"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div className="mt-8">
<p className="text-sm text-center text-gray-600">
Create your own forms and collect submissions by creating a
snoopForms account.
</p>
<div className="mt-6">
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label
htmlFor="firstname"
className="block text-sm font-medium text-ui-gray-dark"
>
First name
</label>
<div className="mt-1">
<input
id="firstname"
name="firstname"
type="text"
autoComplete="given-name"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<label
htmlFor="lastname"
className="block text-sm font-medium text-ui-gray-dark"
>
Last name
</label>
<div className="mt-1">
<input
id="lastname"
name="lastname"
type="text"
autoComplete="family-name"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div>
<label
htmlFor="lastname"
className="block text-sm font-medium text-ui-gray-dark"
>
Last name
</label>
<div className="mt-1">
<input
id="lastname"
name="lastname"
type="text"
autoComplete="family-name"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Email address
</label>
<div className="mt-1">
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Email address
</label>
<div className="mt-1">
<input
id="email"
name="email"
type="email"
autoComplete="email"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Password
</label>
<div className="mt-1">
<input
id="password"
name="password"
type="password"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
/>
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-ui-gray-dark"
>
Password
</label>
<div className="mt-1">
<input
id="password"
name="password"
type="password"
required
className="block w-full px-3 py-2 border rounded-md shadow-sm appearance-none placeholder-ui-gray-medium border-ui-gray-medium focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm ph-no-capture"
/>
</div>
</div>
</div>
<div>
<button
type="submit"
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white border border-transparent rounded-md shadow-sm bg-red hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Sign up
</button>
<div className="mt-3 text-xs text-center text-gray-600">
Already have an account?{" "}
<Link href="/auth/signin">
<a className="text-red hover:text-red-600">Log in.</a>
</Link>
<div>
<button
type="submit"
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white border border-transparent rounded-md shadow-sm bg-red hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Sign up
</button>
<div className="mt-3 text-xs text-center text-gray-600">
Already have an account?{" "}
<Link href="/auth/signin">
<a className="text-red hover:text-red-600">Log in.</a>
</Link>
</div>
</div>
</div>
</form>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</BaseLayoutUnauthorized>
);
}

View File

@@ -1,6 +1,7 @@
import Image from "next/image";
import { useRouter } from "next/router";
import { toast } from "react-toastify";
import BaseLayoutUnauthorized from "../../components/layout/BaseLayoutUnauthorized";
import { resendVerificationEmail } from "../../lib/users";
interface props {
@@ -20,49 +21,51 @@ export default function SignIn({}: props) {
}
};
return (
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<BaseLayoutUnauthorized title="Verify your email">
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<div>
<Image
src="/img/snoopforms-logo.svg"
alt="snoopForms logo"
width={500}
height={89}
/>
</div>
<div className="mt-8">
{email ? (
<>
<h1 className="mb-4 font-bold text-center leading-2">
Please verify your email address
</h1>
<p className="text-center">
We have sent you an email to the address{" "}
<span className="italic">{router.query.email}</span>. Please
click the link in the email to activate your account.
</p>
<hr className="my-4" />
<p className="text-xs text-center">
You didn&apos;t receive an email or your link expired?
<br />
Click the button below to request a new email.
</p>
<button
type="button"
onClick={() => requestVerificationEmail()}
className="flex justify-center w-full px-4 py-2 mt-5 text-sm font-medium text-gray-600 bg-white border border-gray-400 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Request a new verification mail
</button>{" "}
</>
) : (
<p className="text-center">No E-Mail Address provided</p>
)}
<div className="mt-8">
{email ? (
<>
<h1 className="mb-4 font-bold text-center leading-2">
Please verify your email address
</h1>
<p className="text-center">
We have sent you an email to the address{" "}
<span className="italic">{router.query.email}</span>. Please
click the link in the email to activate your account.
</p>
<hr className="my-4" />
<p className="text-xs text-center">
You didn&apos;t receive an email or your link expired?
<br />
Click the button below to request a new email.
</p>
<button
type="button"
onClick={() => requestVerificationEmail()}
className="flex justify-center w-full px-4 py-2 mt-5 text-sm font-medium text-gray-600 bg-white border border-gray-400 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
Request a new verification mail
</button>{" "}
</>
) : (
<p className="text-center">No E-Mail Address provided</p>
)}
</div>
</div>
</div>
</div>
</div>
</BaseLayoutUnauthorized>
);
}

View File

@@ -1,6 +1,7 @@
import { signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import BaseLayoutUnauthorized from "../../components/layout/BaseLayoutUnauthorized";
export default function Verify() {
const router = useRouter();
@@ -14,14 +15,16 @@ export default function Verify() {
}
}, [token]);
return (
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<p className="text-center">
{!token ? "No Token provided" : "Verifying..."}
</p>
<BaseLayoutUnauthorized title="Verifying your email">
<div className="flex min-h-screen bg-ui-gray-light">
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
<div className="w-full max-w-sm p-8 mx-auto bg-white rounded-xl shadow-cont lg:w-96">
<p className="text-center">
{!token ? "No Token provided" : "Verifying..."}
</p>
</div>
</div>
</div>
</div>
</BaseLayoutUnauthorized>
);
}

View File

@@ -1,10 +1,11 @@
import { GetServerSideProps } from "next";
import { getSession } from "next-auth/react";
import Head from "next/head";
import { useRouter } from "next/router";
import App from "../../components/frontend/App";
import BaseLayoutUnauthorized from "../../components/layout/BaseLayoutUnauthorized";
import Loading from "../../components/Loading";
import { useNoCodeFormPublic } from "../../lib/noCodeForm";
import { usePosthog } from "../../lib/posthog";
export default function Share({}) {
const router = useRouter();
@@ -12,6 +13,8 @@ export default function Share({}) {
const { noCodeForm, isLoadingNoCodeForm, isErrorNoCodeForm } =
useNoCodeFormPublic(formId);
usePosthog(null, true);
if (isErrorNoCodeForm) {
return <p>Not found</p>;
}
@@ -21,12 +24,9 @@ export default function Share({}) {
}
return (
<>
<Head>
<title>SnoopForms</title>
</Head>
<BaseLayoutUnauthorized title="snoopForms">
<App formId={formId} blocks={noCodeForm.blocks} />
</>
</BaseLayoutUnauthorized>
);
}

View File

@@ -257,6 +257,11 @@
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz"
integrity sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==
"@sentry/types@^7.2.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.7.0.tgz#dd6bd3d119d7efea0e85dbaa4b17de1c22b63c7a"
integrity sha512-4x8O7uerSGLnYC10krHl9t8h7xXHn5FextqKYbTCXCnx2hC8D+9lz8wcbQAFo0d97wiUYqI8opmEgFVGx7c5hQ==
"@snoopforms/react@^0.0.4":
version "0.0.4"
resolved "https://registry.yarnpkg.com/@snoopforms/react/-/react-0.0.4.tgz#256c2285d0ef540c6ba4bde8d9a096d02e576fff"
@@ -1209,6 +1214,11 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fflate@^0.4.1:
version "0.4.8"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
@@ -2159,6 +2169,15 @@ postcss@^8.4.13, postcss@^8.4.14:
picocolors "^1.0.0"
source-map-js "^1.0.2"
posthog-js@^1.26.0:
version "1.26.0"
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.26.0.tgz#8fd2becfbdf8f165244043d109f140ea0d02a99b"
integrity sha512-Fjc5REUJxrVTQ0WzfChn+CW/UrparZGwINPOtO9FoB25U2IrXnvnTUpkYhSPucZPWUwUMRdXBCo9838COn464Q==
dependencies:
"@sentry/types" "^7.2.0"
fflate "^0.4.1"
rrweb-snapshot "^1.1.14"
preact-render-to-string@^5.1.19:
version "5.2.0"
resolved "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.0.tgz"
@@ -2363,6 +2382,11 @@ rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
rrweb-snapshot@^1.1.14:
version "1.1.14"
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-1.1.14.tgz#9d4d9be54a28a893373428ee4393ec7e5bd83fcc"
integrity sha512-eP5pirNjP5+GewQfcOQY4uBiDnpqxNRc65yKPW0eSoU1XamDfc4M8oqpXGMyUyvLyxFDB0q0+DChuxxiU2FXBQ==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"