docs: track code copy + AI assistant event (#14193)
* docs: track code copy + AI assistant event * add pathname to callback
This commit is contained in:
1 parent
ef162f8b5f
commit
00052b9e50
12 files changed
+73
-62
No files matched your search
@@ -1,23 +1,24 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Feedback as UiFeedback, FeedbackProps } from "docs-ui"
|
import {
|
||||||
import { usePathname } from "next/navigation"
|
Feedback as UiFeedback,
|
||||||
|
FeedbackProps,
|
||||||
|
DocsTrackingEvents,
|
||||||
|
} from "docs-ui"
|
||||||
import { useArea } from "../../providers/area"
|
import { useArea } from "../../providers/area"
|
||||||
|
|
||||||
export const Feedback = (props: Partial<FeedbackProps>) => {
|
export const Feedback = (props: Partial<FeedbackProps>) => {
|
||||||
const pathname = usePathname()
|
|
||||||
const { area } = useArea()
|
const { area } = useArea()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
vertical={true}
|
vertical={true}
|
||||||
{...props}
|
{...props}
|
||||||
event="survey_api-ref"
|
event={DocsTrackingEvents.SURVEY_API}
|
||||||
extraData={{
|
extraData={{
|
||||||
area,
|
area,
|
||||||
...props.extraData,
|
...props.extraData,
|
||||||
}}
|
}}
|
||||||
pathName={`/api/${pathname}`}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,17 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
DocsTrackingEvents,
|
||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
|
||||||
import { basePathUrl } from "../../utils/base-path-url"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event={DocsTrackingEvents.SURVEY}
|
||||||
pathName={feedbackPathname}
|
|
||||||
question={props.question || "Was this chapter helpful?"}
|
question={props.question || "Was this chapter helpful?"}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
DocsTrackingEvents,
|
||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
|
||||||
import { basePathUrl } from "../../utils/base-path-url"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event={DocsTrackingEvents.SURVEY}
|
||||||
pathName={feedbackPathname}
|
|
||||||
question="Was this guide helpful?"
|
question="Was this guide helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
DocsTrackingEvents,
|
||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
import { basePathUrl } from "../../utils/base-path-url"
|
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
export const Feedback = (props: FeedbackProps) => {
|
export const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event={DocsTrackingEvents.SURVEY}
|
||||||
pathName={feedbackPathname}
|
|
||||||
question="Was this page helpful?"
|
question="Was this page helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
DocsTrackingEvents,
|
||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
|
||||||
import { basePathUrl } from "../../utils/base-path-url"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event={DocsTrackingEvents.SURVEY}
|
||||||
pathName={feedbackPathname}
|
|
||||||
question="Was this guide helpful?"
|
question="Was this guide helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
DocsTrackingEvents,
|
||||||
Feedback as UiFeedback,
|
Feedback as UiFeedback,
|
||||||
FeedbackProps as UiFeedbackProps,
|
FeedbackProps as UiFeedbackProps,
|
||||||
} from "docs-ui"
|
} from "docs-ui"
|
||||||
import { usePathname } from "next/navigation"
|
|
||||||
import { basePathUrl } from "../../utils/base-path-url"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
|
|
||||||
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
type FeedbackProps = Omit<UiFeedbackProps, "event" | "pathName">
|
||||||
|
|
||||||
const Feedback = (props: FeedbackProps) => {
|
const Feedback = (props: FeedbackProps) => {
|
||||||
const pathname = usePathname()
|
|
||||||
|
|
||||||
const feedbackPathname = useMemo(() => basePathUrl(pathname), [pathname])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiFeedback
|
<UiFeedback
|
||||||
event="survey"
|
event={DocsTrackingEvents.SURVEY}
|
||||||
pathName={feedbackPathname}
|
|
||||||
question="Was this guide helpful?"
|
question="Was this guide helpful?"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import React, { useEffect, useMemo, useRef } from "react"
|
import React, { useEffect, useMemo, useRef } from "react"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { ArrowUpCircleSolid, LightBulb, LightBulbSolid } from "@medusajs/icons"
|
import { ArrowUpCircleSolid, LightBulb, LightBulbSolid } from "@medusajs/icons"
|
||||||
import { useAiAssistant, useIsBrowser } from "../../../../providers"
|
import {
|
||||||
|
useAiAssistant,
|
||||||
|
useAnalytics,
|
||||||
|
useIsBrowser,
|
||||||
|
} from "../../../../providers"
|
||||||
import { useChat, useDeepThinking } from "@kapaai/react-sdk"
|
import { useChat, useDeepThinking } from "@kapaai/react-sdk"
|
||||||
import { useAiAssistantChatNavigation } from "../../../../hooks"
|
import { useAiAssistantChatNavigation } from "../../../../hooks"
|
||||||
import { Tooltip } from "../../../Tooltip"
|
import { Tooltip } from "../../../Tooltip"
|
||||||
|
import { DocsTrackingEvents } from "../../../../constants"
|
||||||
|
|
||||||
type AiAssistantChatWindowInputProps = {
|
type AiAssistantChatWindowInputProps = {
|
||||||
chatWindowRef: React.RefObject<HTMLDivElement | null>
|
chatWindowRef: React.RefObject<HTMLDivElement | null>
|
||||||
@@ -16,6 +21,7 @@ export const AiAssistantChatWindowInput = ({
|
|||||||
const { chatOpened, inputRef, loading, setChatOpened, isCaptchaLoaded } =
|
const { chatOpened, inputRef, loading, setChatOpened, isCaptchaLoaded } =
|
||||||
useAiAssistant()
|
useAiAssistant()
|
||||||
const { submitQuery, conversation } = useChat()
|
const { submitQuery, conversation } = useChat()
|
||||||
|
const { track } = useAnalytics()
|
||||||
const { active, toggle } = useDeepThinking()
|
const { active, toggle } = useDeepThinking()
|
||||||
const { isBrowser } = useIsBrowser()
|
const { isBrowser } = useIsBrowser()
|
||||||
const { searchQuery, searchQueryType } = useMemo(() => {
|
const { searchQuery, searchQueryType } = useMemo(() => {
|
||||||
@@ -38,6 +44,13 @@ export const AiAssistantChatWindowInput = ({
|
|||||||
) => {
|
) => {
|
||||||
e?.preventDefault()
|
e?.preventDefault()
|
||||||
submitQuery(overrideQuestion || question)
|
submitQuery(overrideQuestion || question)
|
||||||
|
if (!conversation.length) {
|
||||||
|
track({
|
||||||
|
event: {
|
||||||
|
event: DocsTrackingEvents.AI_ASSISTANT_START_CHAT,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
setQuestion("")
|
setQuestion("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import React, { useEffect, useState } from "react"
|
import React, { useEffect, useState } from "react"
|
||||||
import { CopyButton } from "../../../.."
|
import { CopyButton, DocsTrackingEvents, useAnalytics } from "../../../.."
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { CheckMini, SquareTwoStack } from "@medusajs/icons"
|
import { CheckMini, SquareTwoStack } from "@medusajs/icons"
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ export const CodeBlockCopyAction = ({
|
|||||||
inHeader,
|
inHeader,
|
||||||
}: CodeBlockCopyActionProps) => {
|
}: CodeBlockCopyActionProps) => {
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
|
const { track } = useAnalytics()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (copied) {
|
if (copied) {
|
||||||
@@ -22,6 +23,12 @@ export const CodeBlockCopyAction = ({
|
|||||||
setCopied(false)
|
setCopied(false)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
track({
|
||||||
|
event: {
|
||||||
|
event: DocsTrackingEvents.CODE_BLOCK_COPY,
|
||||||
|
},
|
||||||
|
})
|
||||||
}, [copied])
|
}, [copied])
|
||||||
|
|
||||||
const iconClassName = [
|
const iconClassName = [
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import React, { useEffect, useMemo, useRef, useState } from "react"
|
|||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { Highlight, HighlightProps, themes, Token } from "prism-react-renderer"
|
import { Highlight, HighlightProps, themes, Token } from "prism-react-renderer"
|
||||||
import { ApiRunner } from "@/components"
|
import { ApiRunner } from "@/components"
|
||||||
import { useColorMode } from "@/providers"
|
import { useAnalytics, useColorMode } from "@/providers"
|
||||||
import { CodeBlockHeader, CodeBlockHeaderMeta } from "./Header"
|
import { CodeBlockHeader, CodeBlockHeaderMeta } from "./Header"
|
||||||
import { CodeBlockLine } from "./Line"
|
import { CodeBlockLine } from "./Line"
|
||||||
import { ApiAuthType, ApiDataOptions, ApiMethod } from "types"
|
import { ApiAuthType, ApiDataOptions, ApiMethod } from "types"
|
||||||
// @ts-expect-error can't install the types package because it doesn't support React v19
|
// @ts-expect-error can't install the types package because it doesn't support React v19
|
||||||
import { CSSTransition } from "react-transition-group"
|
import { CSSTransition } from "react-transition-group"
|
||||||
import { useCollapsibleCodeLines } from "../.."
|
import { DocsTrackingEvents, useCollapsibleCodeLines } from "../.."
|
||||||
import { HighlightProps as CollapsibleHighlightProps } from "@/hooks"
|
import { HighlightProps as CollapsibleHighlightProps } from "@/hooks"
|
||||||
import { CodeBlockActions, CodeBlockActionsProps } from "./Actions"
|
import { CodeBlockActions, CodeBlockActionsProps } from "./Actions"
|
||||||
import { CodeBlockCollapsibleButton } from "./Collapsible/Button"
|
import { CodeBlockCollapsibleButton } from "./Collapsible/Button"
|
||||||
@@ -103,6 +103,7 @@ export const CodeBlock = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { colorMode } = useColorMode()
|
const { colorMode } = useColorMode()
|
||||||
|
const { track } = useAnalytics()
|
||||||
const [showTesting, setShowTesting] = useState(false)
|
const [showTesting, setShowTesting] = useState(false)
|
||||||
const codeContainerRef = useRef<HTMLDivElement>(null)
|
const codeContainerRef = useRef<HTMLDivElement>(null)
|
||||||
const codeRef = useRef<HTMLElement>(null)
|
const codeRef = useRef<HTMLElement>(null)
|
||||||
@@ -296,6 +297,14 @@ export const CodeBlock = ({
|
|||||||
)
|
)
|
||||||
}, [codeContainerRef.current, codeRef.current])
|
}, [codeContainerRef.current, codeRef.current])
|
||||||
|
|
||||||
|
const trackCopy = () => {
|
||||||
|
track({
|
||||||
|
event: {
|
||||||
|
event: DocsTrackingEvents.CODE_BLOCK_COPY,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const actionsProps: Omit<CodeBlockActionsProps, "inHeader"> = useMemo(
|
const actionsProps: Omit<CodeBlockActionsProps, "inHeader"> = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
source,
|
source,
|
||||||
@@ -435,6 +444,7 @@ export const CodeBlock = ({
|
|||||||
"pl-docs_1",
|
"pl-docs_1",
|
||||||
preClassName
|
preClassName
|
||||||
)}
|
)}
|
||||||
|
onCopy={trackCopy}
|
||||||
>
|
>
|
||||||
<code
|
<code
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { RadioGroup } from "@medusajs/ui"
|
|||||||
|
|
||||||
export type FeedbackProps = {
|
export type FeedbackProps = {
|
||||||
event: string
|
event: string
|
||||||
pathName: string
|
|
||||||
reportLink?: string
|
reportLink?: string
|
||||||
question?: string
|
question?: string
|
||||||
positiveBtn?: string
|
positiveBtn?: string
|
||||||
@@ -55,7 +54,6 @@ const feedbackOptions = {
|
|||||||
|
|
||||||
export const Feedback = ({
|
export const Feedback = ({
|
||||||
event,
|
event,
|
||||||
pathName,
|
|
||||||
reportLink: initReportLink,
|
reportLink: initReportLink,
|
||||||
question = "Was this page helpful?",
|
question = "Was this page helpful?",
|
||||||
positiveBtn = "It was helpful",
|
positiveBtn = "It was helpful",
|
||||||
@@ -106,15 +104,12 @@ export const Feedback = ({
|
|||||||
event: {
|
event: {
|
||||||
event,
|
event,
|
||||||
options: {
|
options: {
|
||||||
url: pathName,
|
|
||||||
label: document.title,
|
|
||||||
feedback:
|
feedback:
|
||||||
(feedback !== null && feedback) ||
|
(feedback !== null && feedback) ||
|
||||||
(feedback === null && positiveFeedback)
|
(feedback === null && positiveFeedback)
|
||||||
? "yes"
|
? "yes"
|
||||||
: "no",
|
: "no",
|
||||||
message: message?.length ? message : null,
|
message: message?.length ? message : null,
|
||||||
os: window.navigator.userAgent,
|
|
||||||
feedbackOption,
|
feedbackOption,
|
||||||
...extraData,
|
...extraData,
|
||||||
},
|
},
|
||||||
@@ -124,7 +119,6 @@ export const Feedback = ({
|
|||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tracker: ["segment", "posthog"],
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -494,3 +494,10 @@ export const products: Product[] = [
|
|||||||
image: "/images/user-icon.png",
|
image: "/images/user-icon.png",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export enum DocsTrackingEvents {
|
||||||
|
SURVEY = "survey",
|
||||||
|
SURVEY_API = "survey_api-ref",
|
||||||
|
CODE_BLOCK_COPY = "code_block_copy",
|
||||||
|
AI_ASSISTANT_START_CHAT = "ai_assistant_start_chat",
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import React, {
|
|||||||
import { useSegmentAnalytics } from "./providers/segment"
|
import { useSegmentAnalytics } from "./providers/segment"
|
||||||
import { usePostHogAnalytics } from "./providers/posthog"
|
import { usePostHogAnalytics } from "./providers/posthog"
|
||||||
import { useReoDevAnalytics } from "./providers/reo-dev"
|
import { useReoDevAnalytics } from "./providers/reo-dev"
|
||||||
|
import { usePathname } from "next/navigation"
|
||||||
|
|
||||||
export type ExtraData = {
|
export type ExtraData = {
|
||||||
section?: string
|
section?: string
|
||||||
@@ -43,6 +44,8 @@ export type AnalyticsProviderProps = {
|
|||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_TRACKER: Trackers = "posthog"
|
||||||
|
|
||||||
export const AnalyticsProvider = ({
|
export const AnalyticsProvider = ({
|
||||||
segmentWriteKey,
|
segmentWriteKey,
|
||||||
reoDevKey,
|
reoDevKey,
|
||||||
@@ -55,12 +58,23 @@ export const AnalyticsProvider = ({
|
|||||||
})
|
})
|
||||||
const { track: trackWithPostHog } = usePostHogAnalytics()
|
const { track: trackWithPostHog } = usePostHogAnalytics()
|
||||||
useReoDevAnalytics({ reoDevKey })
|
useReoDevAnalytics({ reoDevKey })
|
||||||
|
const pathname = usePathname()
|
||||||
|
|
||||||
const processEvent = useCallback(
|
const processEvent = useCallback(
|
||||||
async (event: TrackedEvent) => {
|
async (event: TrackedEvent) => {
|
||||||
const trackers = Array.isArray(event.tracker)
|
const trackers = !event.tracker
|
||||||
|
? [DEFAULT_TRACKER]
|
||||||
|
: Array.isArray(event.tracker)
|
||||||
? event.tracker
|
? event.tracker
|
||||||
: [event.tracker]
|
: [event.tracker]
|
||||||
|
|
||||||
|
event.options = {
|
||||||
|
url: pathname,
|
||||||
|
label: document.title,
|
||||||
|
os: window.navigator.userAgent,
|
||||||
|
...event.options,
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
trackers.map(async (tracker) => {
|
trackers.map(async (tracker) => {
|
||||||
switch (tracker) {
|
switch (tracker) {
|
||||||
@@ -73,7 +87,7 @@ export const AnalyticsProvider = ({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[trackWithSegment, trackWithPostHog]
|
[trackWithSegment, trackWithPostHog, pathname]
|
||||||
)
|
)
|
||||||
|
|
||||||
const track = ({ event }: { event: TrackedEvent }) => {
|
const track = ({ event }: { event: TrackedEvent }) => {
|
||||||
|
|||||||
Reference in new issue
Block a user