fix: properly attribute revenue with posthog

This commit is contained in:
Dhravya Shah 2026-02-25 18:28:13 -08:00
parent c82dcdc30a
commit 0c46362505
8 changed files with 309 additions and 93 deletions

View file

@ -273,7 +273,6 @@ export default defineBackground(() => {
})()
return true
}
},
)
})

View file

@ -65,25 +65,16 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
const memorySchema = z.object({
content: z
.string()
.max(
200000,
"Content exceeds maximum length of 200,000 characters",
)
.max(200000, "Content exceeds maximum length of 200,000 characters")
.describe("The memory content to save or forget"),
action: z
.enum(["save", "forget"])
.optional()
.default("save"),
action: z.enum(["save", "forget"]).optional().default("save"),
...(hasRootContainerTag ? {} : containerTagField),
})
const recallSchema = z.object({
query: z
.string()
.max(
1000,
"Query exceeds maximum length of 1,000 characters",
)
.max(1000, "Query exceeds maximum length of 1,000 characters")
.describe("The search query to find relevant memories"),
includeProfile: z.boolean().optional().default(true),
...(hasRootContainerTag ? {} : containerTagField),

View file

@ -59,8 +59,9 @@ export function ConnectContent({ selectedProject }: ConnectContentProps) {
useEffect(() => {
if (!autumn.isLoading) {
setIsProUser(
autumn.customer?.products?.some((product) => product.id === "api_pro") ??
false,
autumn.customer?.products?.some(
(product) => product.id === "api_pro",
) ?? false,
)
}
}, [autumn.isLoading, autumn.customer])

View file

@ -29,14 +29,25 @@ const TOOL_META: Record<string, { label: string; icon: typeof SearchIcon }> = {
cancelSchedule: { label: "Cancel Schedule", icon: XCircleIcon },
}
function ToolCallDisplay({ part }: { part: { type: string; state: string; input?: unknown; output?: unknown; toolCallId?: string } }) {
function ToolCallDisplay({
part,
}: {
part: {
type: string
state: string
input?: unknown
output?: unknown
toolCallId?: string
}
}) {
const [expanded, setExpanded] = useState(false)
const toolName = part.type.replace("tool-", "")
const meta = TOOL_META[toolName]
const Icon = meta?.icon ?? WrenchIcon
const label = meta?.label ?? toolName
const isLoading = part.state === "input-streaming" || part.state === "input-available"
const isLoading =
part.state === "input-streaming" || part.state === "input-available"
const isDone = part.state === "output-available"
const isError = part.state === "error"
@ -53,9 +64,27 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input?
{isLoading ? (
<Loader2 className="size-3 animate-spin text-blue-400 shrink-0" />
) : (
<Icon className={cn("size-3 shrink-0", isDone ? "text-emerald-400" : isError ? "text-red-400" : "text-white/50")} />
<Icon
className={cn(
"size-3 shrink-0",
isDone
? "text-emerald-400"
: isError
? "text-red-400"
: "text-white/50",
)}
/>
)}
<span className={cn("font-medium", isDone ? "text-emerald-400" : isError ? "text-red-400" : "text-blue-400")}>
<span
className={cn(
"font-medium",
isDone
? "text-emerald-400"
: isError
? "text-red-400"
: "text-blue-400",
)}
>
{label}
</span>
{isLoading && <span className="text-white/40 ml-auto">running...</span>}
@ -74,7 +103,9 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input?
<div>
<div className="text-white/40 mb-1">Input</div>
<pre className="text-white/70 bg-[#080B10] rounded p-2 overflow-x-auto max-h-40 overflow-y-auto whitespace-pre-wrap break-all">
{typeof part.input === "string" ? part.input : JSON.stringify(part.input, null, 2)}
{typeof part.input === "string"
? part.input
: JSON.stringify(part.input, null, 2)}
</pre>
</div>
)}
@ -82,7 +113,9 @@ function ToolCallDisplay({ part }: { part: { type: string; state: string; input?
<div>
<div className="text-white/40 mb-1">Output</div>
<pre className="text-white/70 bg-[#080B10] rounded p-2 overflow-x-auto max-h-40 overflow-y-auto whitespace-pre-wrap break-all">
{typeof part.output === "string" ? part.output : JSON.stringify(part.output, null, 2)}
{typeof part.output === "string"
? part.output
: JSON.stringify(part.output, null, 2)}
</pre>
</div>
)}

View file

@ -47,7 +47,8 @@ const PLUGIN_CATALOG: Record<string, PluginInfo> = {
claude_code: {
id: "claude_code",
name: "Claude Code",
description: "Persistent memory for Claude Code. Remembers your coding context, patterns, and decisions across sessions.",
description:
"Persistent memory for Claude Code. Remembers your coding context, patterns, and decisions across sessions.",
features: [
"Auto-recalls relevant context at session start",
"Captures important observations from tool usage",
@ -60,7 +61,8 @@ const PLUGIN_CATALOG: Record<string, PluginInfo> = {
opencode: {
id: "opencode",
name: "OpenCode",
description: "Memory layer for OpenCode. Enhances your coding assistant with long-term memory capabilities.",
description:
"Memory layer for OpenCode. Enhances your coding assistant with long-term memory capabilities.",
features: [
"Semantic search across previous sessions",
"Auto-capture of coding decisions",
@ -72,7 +74,8 @@ const PLUGIN_CATALOG: Record<string, PluginInfo> = {
clawdbot: {
id: "clawdbot",
name: "ClawdBot",
description: "Multi-platform memory for OpenClaw. Works across Telegram, WhatsApp, Discord, Slack and more.",
description:
"Multi-platform memory for OpenClaw. Works across Telegram, WhatsApp, Discord, Slack and more.",
features: [
"Cross-channel memory persistence",
"Automatic conversation capture",
@ -98,18 +101,26 @@ export function PluginsDetail() {
const autumn = useCustomer()
const queryClient = useQueryClient()
const [connectingPlugin, setConnectingPlugin] = useState<string | null>(null)
const [newKey, setNewKey] = useState<{ open: boolean; key: string }>({ open: false, key: "" })
const [newKey, setNewKey] = useState<{ open: boolean; key: string }>({
open: false,
key: "",
})
const [keyCopied, setKeyCopied] = useState(false)
const { data: status = { api_pro: { allowed: false, status: null } }, isLoading: isCheckingStatus } =
fetchSubscriptionStatus(autumn, !autumn.isLoading)
const {
data: status = { api_pro: { allowed: false, status: null } },
isLoading: isCheckingStatus,
} = fetchSubscriptionStatus(autumn, !autumn.isLoading)
const hasProProduct = status.api_pro?.status !== null
const { data: pluginsData } = useQuery({
queryFn: async () => {
const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const res = await fetch(`${API_URL}/v3/auth/plugins`, { credentials: "include" })
const API_URL =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const res = await fetch(`${API_URL}/v3/auth/plugins`, {
credentials: "include",
})
if (!res.ok) throw new Error("Failed to fetch plugins")
return (await res.json()) as { plugins: string[] }
},
@ -133,9 +144,13 @@ export function PluginsDetail() {
for (const key of apiKeys) {
if (!key.metadata) continue
try {
const metadata = typeof key.metadata === "string"
? (JSON.parse(key.metadata) as { sm_type?: string; sm_client?: string })
: (key.metadata as { sm_type?: string; sm_client?: string })
const metadata =
typeof key.metadata === "string"
? (JSON.parse(key.metadata) as {
sm_type?: string
sm_client?: string
})
: (key.metadata as { sm_type?: string; sm_client?: string })
if (metadata.sm_type === "plugin_auth" && metadata.sm_client) {
plugins.push({
@ -152,15 +167,23 @@ export function PluginsDetail() {
return plugins
}, [apiKeys])
const connectedPluginIds = useMemo(() => connectedPlugins.map((p) => p.pluginId), [connectedPlugins])
const connectedPluginIds = useMemo(
() => connectedPlugins.map((p) => p.pluginId),
[connectedPlugins],
)
const createPluginKeyMutation = useMutation({
mutationFn: async (pluginId: string) => {
const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const API_URL =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
const params = new URLSearchParams({ client: pluginId })
const res = await fetch(`${API_URL}/v3/auth/key?${params}`, { credentials: "include" })
const res = await fetch(`${API_URL}/v3/auth/key?${params}`, {
credentials: "include",
})
if (!res.ok) {
const errorData = (await res.json().catch(() => ({}))) as { message?: string }
const errorData = (await res.json().catch(() => ({}))) as {
message?: string
}
throw new Error(errorData.message || "Failed to create plugin key")
}
return (await res.json()) as { key: string }
@ -193,7 +216,10 @@ export function PluginsDetail() {
const handleUpgrade = async () => {
try {
await autumn.attach({ productId: "api_pro", successUrl: "https://app.supermemory.ai/?view=integrations" })
await autumn.attach({
productId: "api_pro",
successUrl: "https://app.supermemory.ai/?view=integrations",
})
window.location.reload()
} catch (error) {
console.error(error)
@ -218,36 +244,75 @@ export function PluginsDetail() {
<>
{/* Marketing hero for free users */}
{!hasProProduct && !isLoading && (
<div className={cn(
"bg-gradient-to-br from-[#0D121A] to-[#14161A] rounded-[14px] p-6 border border-[#4BA0FA]/20",
"shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]",
)}>
<div
className={cn(
"bg-gradient-to-br from-[#0D121A] to-[#14161A] rounded-[14px] p-6 border border-[#4BA0FA]/20",
"shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]",
)}
>
<div className="flex flex-col gap-5">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-[#4BA0FA]/10 shrink-0">
<Zap className="size-6 text-[#4BA0FA]" />
</div>
<div className="flex-1">
<h3 className={cn(dmSans125ClassName(), "font-semibold text-[18px] text-[#FAFAFA]")}>
<h3
className={cn(
dmSans125ClassName(),
"font-semibold text-[18px] text-[#FAFAFA]",
)}
>
Unlock Persistent Memory for Your Tools
</h3>
<p className={cn(dmSans125ClassName(), "text-[14px] text-[#737373] mt-1")}>
Upgrade to Pro to connect plugins and give your AI tools long-term memory
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373] mt-1",
)}
>
Upgrade to Pro to connect plugins and give your AI tools
long-term memory
</p>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-3">
{[
{ icon: Brain, title: "Context Retention", desc: "AI remembers your preferences across sessions" },
{ icon: Zap, title: "Instant Recall", desc: "Past decisions surface automatically when relevant" },
{ icon: Key, title: "Secure & Private", desc: "Your data stays yours with encrypted storage" },
{
icon: Brain,
title: "Context Retention",
desc: "AI remembers your preferences across sessions",
},
{
icon: Zap,
title: "Instant Recall",
desc: "Past decisions surface automatically when relevant",
},
{
icon: Key,
title: "Secure & Private",
desc: "Your data stays yours with encrypted storage",
},
].map(({ icon: Icon, title, desc }) => (
<div key={title} className="flex items-start gap-2.5">
<Icon className="mt-0.5 size-4 text-[#4BA0FA] shrink-0" />
<div>
<p className={cn(dmSans125ClassName(), "text-[13px] font-medium text-[#FAFAFA]")}>{title}</p>
<p className={cn(dmSans125ClassName(), "text-[11px] text-[#737373]")}>{desc}</p>
<p
className={cn(
dmSans125ClassName(),
"text-[13px] font-medium text-[#FAFAFA]",
)}
>
{title}
</p>
<p
className={cn(
dmSans125ClassName(),
"text-[11px] text-[#737373]",
)}
>
{desc}
</p>
</div>
</div>
))}
@ -255,11 +320,25 @@ export function PluginsDetail() {
<div className="flex items-center gap-3">
{Object.values(PLUGIN_CATALOG).map((plugin) => (
<div key={plugin.id} className="flex h-9 w-9 items-center justify-center rounded-lg border border-[#1E293B] bg-[#080B0F]">
<Image alt={plugin.name} className="size-5" height={20} src={plugin.icon} width={20} />
<div
key={plugin.id}
className="flex h-9 w-9 items-center justify-center rounded-lg border border-[#1E293B] bg-[#080B0F]"
>
<Image
alt={plugin.name}
className="size-5"
height={20}
src={plugin.icon}
width={20}
/>
</div>
))}
<span className={cn(dmSans125ClassName(), "text-[12px] text-[#737373]")}>
<span
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#737373]",
)}
>
Claude Code, OpenCode, ClawdBot & more
</span>
</div>
@ -280,12 +359,27 @@ export function PluginsDetail() {
</div>
)}
<div className={cn("bg-[#14161A] rounded-[14px] p-6 relative overflow-hidden", "shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]")}>
<div className={cn("flex flex-col gap-6", !hasProProduct && !isLoading && "opacity-30 pointer-events-none")}>
<div
className={cn(
"bg-[#14161A] rounded-[14px] p-6 relative overflow-hidden",
"shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]",
)}
>
<div
className={cn(
"flex flex-col gap-6",
!hasProProduct && !isLoading && "opacity-30 pointer-events-none",
)}
>
{/* Connected plugins */}
{connectedPlugins.length > 0 && (
<div className="flex flex-col gap-3">
<span className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#FAFAFA]")}>
<span
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#FAFAFA]",
)}
>
Connected Plugins
</span>
{connectedPlugins.map((plugin) => {
@ -293,23 +387,51 @@ export function PluginsDetail() {
return (
<div
key={plugin.id}
className={cn("bg-[#0D121A] border border-[rgba(82,89,102,0.2)] rounded-[12px] px-4 py-3", "shadow-[0px_1px_2px_0px_rgba(0,43,87,0.1)]")}
className={cn(
"bg-[#0D121A] border border-[rgba(82,89,102,0.2)] rounded-[12px] px-4 py-3",
"shadow-[0px_1px_2px_0px_rgba(0,43,87,0.1)]",
)}
>
<div className="flex items-center gap-3">
{info && (
<div className="flex h-10 w-10 items-center justify-center rounded-lg border border-[#1E293B] bg-[#080B0F]">
<Image alt={info.name} className="size-6" height={24} src={info.icon} width={24} />
<Image
alt={info.name}
className="size-6"
height={24}
src={info.icon}
width={24}
/>
</div>
)}
<div className="flex-1">
<p className={cn(dmSans125ClassName(), "font-medium text-[14px] text-[#FAFAFA]")}>
<p
className={cn(
dmSans125ClassName(),
"font-medium text-[14px] text-[#FAFAFA]",
)}
>
{info?.name || plugin.pluginId}
</p>
<div className="flex items-center gap-2">
<div className="size-[7px] rounded-full bg-[#00AC3F]" />
<span className={cn(dmSans125ClassName(), "text-[12px] text-[#00AC3F]")}>Connected</span>
<span
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#00AC3F]",
)}
>
Connected
</span>
{plugin.keyStart && (
<span className={cn(dmSans125ClassName(), "text-[12px] text-[#737373] font-mono")}>{plugin.keyStart}...</span>
<span
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#737373] font-mono",
)}
>
{plugin.keyStart}...
</span>
)}
</div>
</div>
@ -329,8 +451,15 @@ export function PluginsDetail() {
{/* Available plugins */}
<div className="flex flex-col gap-3">
<span className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#FAFAFA]")}>
{connectedPlugins.length > 0 ? "Add More Plugins" : "Available Plugins"}
<span
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#FAFAFA]",
)}
>
{connectedPlugins.length > 0
? "Add More Plugins"
: "Available Plugins"}
</span>
<div className="grid gap-3 md:grid-cols-2 lg:grid-cols-3">
{availablePlugins.map((pluginId) => {
@ -345,23 +474,45 @@ export function PluginsDetail() {
key={pluginId}
className={cn(
"bg-[#0D121A] rounded-[12px] p-4 flex flex-col gap-3 border",
isConnected ? "border-[#4BA0FA]/30" : "border-[rgba(82,89,102,0.2)]",
isConnected
? "border-[#4BA0FA]/30"
: "border-[rgba(82,89,102,0.2)]",
)}
>
<div className="flex items-start gap-3">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border border-[#1E293B] bg-[#080B0F]">
<Image alt={plugin.name} className="size-6" height={24} src={plugin.icon} width={24} />
<Image
alt={plugin.name}
className="size-6"
height={24}
src={plugin.icon}
width={24}
/>
</div>
<div className="flex-1">
<div className="flex items-center gap-2">
<span className={cn(dmSans125ClassName(), "font-medium text-[14px] text-[#FAFAFA]")}>{plugin.name}</span>
<span
className={cn(
dmSans125ClassName(),
"font-medium text-[14px] text-[#FAFAFA]",
)}
>
{plugin.name}
</span>
{isConnected && (
<span className="flex items-center gap-1 text-[10px] text-[#00AC3F] border border-[#00AC3F]/30 rounded-full px-1.5 py-0.5">
<CheckCircle className="size-2.5" /> Connected
</span>
)}
</div>
<p className={cn(dmSans125ClassName(), "text-[12px] text-[#737373] mt-0.5")}>{plugin.description}</p>
<p
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#737373] mt-0.5",
)}
>
{plugin.description}
</p>
</div>
</div>
@ -369,7 +520,14 @@ export function PluginsDetail() {
{plugin.features.map((feature) => (
<li key={feature} className="flex items-start gap-2">
<ArrowRight className="mt-0.5 size-3 shrink-0 text-[#4BA0FA]" />
<span className={cn(dmSans125ClassName(), "text-[12px] text-[#8B8B8B]")}>{feature}</span>
<span
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#8B8B8B]",
)}
>
{feature}
</span>
</li>
))}
</ul>
@ -390,7 +548,9 @@ export function PluginsDetail() {
) : (
<button
type="button"
onClick={() => createPluginKeyMutation.mutate(pluginId)}
onClick={() =>
createPluginKeyMutation.mutate(pluginId)
}
disabled={!!connectingPlugin}
className={cn(
"w-full flex items-center justify-center gap-2 rounded-full h-9 px-4 text-[12px] font-medium",
@ -400,7 +560,10 @@ export function PluginsDetail() {
)}
>
{isCurrentlyConnecting ? (
<><Loader className="size-3.5 animate-spin" /> Connecting...</>
<>
<Loader className="size-3.5 animate-spin" />{" "}
Connecting...
</>
) : (
"Connect Plugin"
)}
@ -412,7 +575,10 @@ export function PluginsDetail() {
href={plugin.docsUrl}
target="_blank"
rel="noopener noreferrer"
className={cn("flex-1 flex items-center justify-center gap-1 text-[11px] text-[#737373] hover:text-white transition-colors", dmSans125ClassName())}
className={cn(
"flex-1 flex items-center justify-center gap-1 text-[11px] text-[#737373] hover:text-white transition-colors",
dmSans125ClassName(),
)}
>
<BookOpen className="size-3" /> Docs
</a>
@ -422,7 +588,10 @@ export function PluginsDetail() {
href={plugin.repoUrl}
target="_blank"
rel="noopener noreferrer"
className={cn("flex-1 flex items-center justify-center gap-1 text-[11px] text-[#737373] hover:text-white transition-colors", dmSans125ClassName())}
className={cn(
"flex-1 flex items-center justify-center gap-1 text-[11px] text-[#737373] hover:text-white transition-colors",
dmSans125ClassName(),
)}
>
<ExternalLink className="size-3" /> GitHub
</a>
@ -438,11 +607,21 @@ export function PluginsDetail() {
</div>
{/* API Key modal */}
<Dialog open={newKey.open} onOpenChange={(open) => setNewKey({ open, key: open ? newKey.key : "" })}>
<Dialog
open={newKey.open}
onOpenChange={(open) =>
setNewKey({ open, key: open ? newKey.key : "" })
}
>
<DialogPortal>
<DialogContent className="bg-[#14161A] border border-white/10 text-[#FAFAFA] md:max-w-md z-100">
<DialogHeader>
<DialogTitle className={cn(dmSans125ClassName(), "text-[#FAFAFA] text-lg font-semibold")}>
<DialogTitle
className={cn(
dmSans125ClassName(),
"text-[#FAFAFA] text-lg font-semibold",
)}
>
Plugin Connected
</DialogTitle>
</DialogHeader>
@ -455,14 +634,21 @@ export function PluginsDetail() {
type="text"
value={newKey.key}
readOnly
className={cn("flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono", dmSans125ClassName())}
className={cn(
"flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono",
dmSans125ClassName(),
)}
/>
<button
type="button"
onClick={handleCopyKey}
className="p-2 rounded-lg bg-[#0D121A] border border-white/10 text-[#737373] hover:text-[#FAFAFA] transition-colors"
>
{keyCopied ? <Check className="h-4 w-4 text-[#4BA0FA]" /> : <Copy className="h-4 w-4" />}
{keyCopied ? (
<Check className="h-4 w-4 text-[#4BA0FA]" />
) : (
<Copy className="h-4 w-4" />
)}
</button>
</div>
<button

View file

@ -1,7 +1,12 @@
"use client"
import { useState, useEffect } from "react"
import { useQueryState, parseAsString, parseAsStringLiteral, parseAsInteger } from "nuqs"
import {
useQueryState,
parseAsString,
parseAsStringLiteral,
parseAsInteger,
} from "nuqs"
import { Button } from "@ui/components/button"
import {
Select,
@ -43,7 +48,9 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) {
const [selectedProject] = useState<string>("sm_project_default")
const [mcpUrlTab, setMcpUrlTab] = useQueryState(
"mcpTab",
parseAsStringLiteral(["oneClick", "manual"] as const).withDefault("oneClick"),
parseAsStringLiteral(["oneClick", "manual"] as const).withDefault(
"oneClick",
),
)
const [isCopied, setIsCopied] = useState(false)
const [activeStep, setActiveStep] = useQueryState(
@ -203,7 +210,9 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) {
: `/mcp-supported-tools/${selectedClient === "claude-code" ? "claude" : selectedClient}.png`
}
/>
<span>{clients[selectedClient as keyof typeof clients]}</span>
<span>
{clients[selectedClient as keyof typeof clients]}
</span>
</div>
) : (
<SelectValue placeholder="Select a client" />

View file

@ -241,7 +241,9 @@ export function ProfileStep({ onSubmit }: ProfileStepProps) {
onClick={() => {
const formData = {
twitter: toXProfileUrl(parseXHandle(twitterHandle)),
linkedin: toLinkedInProfileUrl(parseLinkedInHandle(linkedinProfile)),
linkedin: toLinkedInProfileUrl(
parseLinkedInHandle(linkedinProfile),
),
description: description,
otherLinks: otherLinks
.filter((l) => l.trim())

View file

@ -38,23 +38,18 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (typeof window !== "undefined") {
const posthogKey = "phc_uO09ylgCPmQl3wHukVvvwhphtoIaGmCMUTTwDo3PRlt"
const backendUrl =
process.env.NEXT_PUBLIC_BACKEND_URL ?? "https://api.supermemory.ai"
if (posthogKey) {
posthog.init(posthogKey, {
api_host: `${backendUrl}/orange`,
ui_host: "https://us.i.posthog.com",
person_profiles: "identified_only",
capture_pageview: false,
capture_pageleave: true,
})
} else {
console.warn(
"PostHog API key is not set. PostHog will not be initialized.",
)
}
posthog.init("phc_ShqecfUPQgf16lWu6ZMUzduQvcWzCywrkCz5KHwmWsv", {
api_host: `${backendUrl}/orange`,
ui_host: "https://us.i.posthog.com",
person_profiles: "identified_only",
capture_pageview: false,
capture_pageleave: true,
cookie_domain: ".supermemory.ai",
})
posthog.register({ app: "app" })
}
}, [])