diff --git a/.bun-version b/.bun-version index 26aaba0e8..6085e9465 100644 --- a/.bun-version +++ b/.bun-version @@ -1 +1 @@ -1.2.0 +1.2.1 diff --git a/.changeset/chilled-mirrors-watch.md b/.changeset/chilled-mirrors-watch.md new file mode 100644 index 000000000..3e50ff5ab --- /dev/null +++ b/.changeset/chilled-mirrors-watch.md @@ -0,0 +1,5 @@ +--- +'gitbook': minor +--- + +Track new events for site insights when ads are being clicked diff --git a/bun.lock b/bun.lock index eddb33363..d9c5b4d2b 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "devDependencies": { "@changesets/cli": "^2.27.7", "prettier": "^3.0.3", - "turbo": "^2.1.2", + "turbo": "^2.3.4", }, }, "packages/cache-do": { @@ -32,7 +32,7 @@ "name": "gitbook", "version": "0.5.0", "dependencies": { - "@gitbook/api": "^0.88.1", + "@gitbook/api": "^0.89.0", "@gitbook/cache-do": "workspace:*", "@gitbook/emoji-codepoints": "workspace:*", "@gitbook/icons": "workspace:*", @@ -145,7 +145,7 @@ "name": "@gitbook/react-contentkit", "version": "0.5.1", "dependencies": { - "@gitbook/api": "^0.85.0", + "@gitbook/api": "^0.89.0", "assert-never": "^1.2.1", "classnames": "^2.5.1", }, @@ -425,7 +425,7 @@ "@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="], - "@gitbook/api": ["@gitbook/api@0.85.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^1.1.1" } }, "sha512-hhWFPxdX1zW8gQd7DYlf8R/LzaFWrC+jB9Lg4M4uz0Fcr5nrdbohufu1yMhGNNDTmo8qzv+fYyeTuoVJSV8G8A=="], + "@gitbook/api": ["@gitbook/api@0.89.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-htzPY5OrFrZz29ShhB535e/j0Z6BBRDmdc97qfprJKzUE4zTRv2L20ZZ0dYeSgNFTkSiVhsuv0sfd6njWfNk7w=="], "@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"], @@ -1475,7 +1475,7 @@ "events-intercept": ["events-intercept@2.0.0", "", {}, "sha512-blk1va0zol9QOrdZt0rFXo5KMkNPVSp92Eju/Qz8THwKWKRKeE0T8Br/1aW6+Edkyq9xHYgYxn2QtOnUKPUp+Q=="], - "eventsource-parser": ["eventsource-parser@1.1.2", "", {}, "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA=="], + "eventsource-parser": ["eventsource-parser@3.0.0", "", {}, "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA=="], "execa": ["execa@3.2.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.0", "onetime": "^5.1.0", "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-kJJfVbI/lZE1PZYDI5VPxp8zXPO9rtxOkhpZ0jMKha56AI9y2gGVC6bkukStQf0ka5Rh15BA5m7cCCH4jmHqkw=="], @@ -2619,19 +2619,19 @@ "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], - "turbo": ["turbo@2.1.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.1.3", "turbo-darwin-arm64": "2.1.3", "turbo-linux-64": "2.1.3", "turbo-linux-arm64": "2.1.3", "turbo-windows-64": "2.1.3", "turbo-windows-arm64": "2.1.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-lY0yj2GH2a2a3NExZ3rGe+rHUVeFE2aXuRAue57n+08E7Z7N7YCmynju0kPC1grAQzERmoLpKrmzmWd+PNiADw=="], + "turbo": ["turbo@2.3.4", "", { "optionalDependencies": { "turbo-darwin-64": "2.3.4", "turbo-darwin-arm64": "2.3.4", "turbo-linux-64": "2.3.4", "turbo-linux-arm64": "2.3.4", "turbo-windows-64": "2.3.4", "turbo-windows-arm64": "2.3.4" }, "bin": { "turbo": "bin/turbo" } }, "sha512-1kiLO5C0Okh5ay1DbHsxkPsw9Sjsbjzm6cF85CpWjR0BIyBFNDbKqtUyqGADRS1dbbZoQanJZVj4MS5kk8J42Q=="], - "turbo-darwin-64": ["turbo-darwin-64@2.1.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-ouJOm0g0YyoBuhmikEujVCBGo3Zr0lbSOWFIsQtWUTItC88F2w2byhjtsYGPXQwMlTbXwmoBU2lOCfWNkeEwHQ=="], + "turbo-darwin-64": ["turbo-darwin-64@2.3.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-uOi/cUIGQI7uakZygH+cZQ5D4w+aMLlVCN2KTGot+cmefatps2ZmRRufuHrEM0Rl63opdKD8/JIu+54s25qkfg=="], - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.1.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-j2FOJsK4LAOtHQlb3Oom0yWB/Vi0nF1ljInr311mVzHoFAJRZtfW2fRvdZRb/lBUwjSp8be58qWHzANIcrA0OA=="], + "turbo-darwin-arm64": ["turbo-darwin-arm64@2.3.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-IIM1Lq5R+EGMtM1YFGl4x8Xkr0MWb4HvyU8N4LNoQ1Be5aycrOE+VVfH+cDg/Q4csn+8bxCOxhRp5KmUflrVTQ=="], - "turbo-linux-64": ["turbo-linux-64@2.1.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ubRHkI1gSel7H7wsmxKK8C9UlLWqg/2dkCC88LFupaK6TKgvBKqDqA0Z1M9C/escK0Jsle2k0H8bybV9OYIl4Q=="], + "turbo-linux-64": ["turbo-linux-64@2.3.4", "", { "os": "linux", "cpu": "x64" }, "sha512-1aD2EfR7NfjFXNH3mYU5gybLJEFi2IGOoKwoPLchAFRQ6OEJQj201/oNo9CDL75IIrQo64/NpEgVyZtoPlfhfA=="], - "turbo-linux-arm64": ["turbo-linux-arm64@2.1.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-LffUL+e5wv7BtD6DgnM2kKOlDkMo2eRjhbAjVnrCD3wi2ug0tl6NDzajnHHjtaMyOnIf4AvzSKdLWsBxafGBQA=="], + "turbo-linux-arm64": ["turbo-linux-arm64@2.3.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-MxTpdKwxCaA5IlybPxgGLu54fT2svdqTIxRd0TQmpRJIjM0s4kbM+7YiLk0mOh6dGqlWPUsxz/A0Mkn8Xr5o7Q=="], - "turbo-windows-64": ["turbo-windows-64@2.1.3", "", { "os": "win32", "cpu": "x64" }, "sha512-S9SvcZZoaq5jKr6kA6eF7/xgQhVn8Vh7PVy5lono9zybvhyL4eY++y2PaLToIgL8G9IcbLmgOC73ExNjFBg9XQ=="], + "turbo-windows-64": ["turbo-windows-64@2.3.4", "", { "os": "win32", "cpu": "x64" }, "sha512-yyCrWqcRGu1AOOlrYzRnizEtdkqi+qKP0MW9dbk9OsMDXaOI5jlWtTY/AtWMkLw/czVJ7yS9Ex1vi9DB6YsFvw=="], - "turbo-windows-arm64": ["turbo-windows-arm64@2.1.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-twlEo8lRrGbrR6T/ZklUIquW3IlFCEtywklgVA81aIrSBm56+GEVpSrHhIlsx1hiYeSNrs+GpDwZGe+V7fvEVQ=="], + "turbo-windows-arm64": ["turbo-windows-arm64@2.3.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-PggC3qH+njPfn1PDVwKrQvvQby8X09ufbqZ2Ha4uSu+5TvPorHHkAbZVHKYj2Y+tvVzxRzi4Sv6NdHXBS9Be5w=="], "type": ["type@2.7.3", "", {}, "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="], @@ -3163,8 +3163,6 @@ "fs-minipass/minipass": ["minipass@2.9.0", "", { "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg=="], - "gitbook/@gitbook/api": ["@gitbook/api@0.88.1", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-u+xzuWKbuTe25VTEiFEcZ49Jst8QCVrc6R7MycU4HnS3KKazuCk8gA30JU/JKINkUElMmPLsTOQPY3ZAYvPkVQ=="], - "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "google-auth-library/jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], @@ -3509,8 +3507,6 @@ "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "gitbook/@gitbook/api/eventsource-parser": ["eventsource-parser@3.0.0", "", {}, "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA=="], - "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "google-auth-library/jws/jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], diff --git a/package.json b/package.json index f09330248..9c5913fc8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "devDependencies": { "@changesets/cli": "^2.27.7", "prettier": "^3.0.3", - "turbo": "^2.1.2" + "turbo": "^2.3.4" }, "packageManager": "bun@1.1.18", "overrides": { diff --git a/packages/gitbook/package.json b/packages/gitbook/package.json index e80453a40..83c7726b3 100644 --- a/packages/gitbook/package.json +++ b/packages/gitbook/package.json @@ -16,7 +16,7 @@ "clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static" }, "dependencies": { - "@gitbook/api": "^0.88.1", + "@gitbook/api": "^0.89.0", "@gitbook/cache-do": "workspace:*", "@gitbook/emoji-codepoints": "workspace:*", "@gitbook/icons": "workspace:*", diff --git a/packages/gitbook/src/app/middleware/(space)/~gitbook/pdf/page.tsx b/packages/gitbook/src/app/middleware/(space)/~gitbook/pdf/page.tsx index d13201d53..f98ef81f4 100644 --- a/packages/gitbook/src/app/middleware/(space)/~gitbook/pdf/page.tsx +++ b/packages/gitbook/src/app/middleware/(space)/~gitbook/pdf/page.tsx @@ -4,6 +4,7 @@ import { RevisionPageDocument, RevisionPageGroup, SiteCustomizationSettings, + SiteInsightsTrademarkPlacement, Space, } from '@gitbook/api'; import { Icon } from '@gitbook/icons'; @@ -146,7 +147,11 @@ export default async function PDFHTMLOutput(props: { limit={pdfParams.limit ?? DEFAULT_LIMIT} trademark={ customization.trademark.enabled ? ( - + ) : null } /> diff --git a/packages/gitbook/src/components/Ads/Ad.tsx b/packages/gitbook/src/components/Ads/Ad.tsx index 4a15b862d..827ec6cd3 100644 --- a/packages/gitbook/src/components/Ads/Ad.tsx +++ b/packages/gitbook/src/components/Ads/Ad.tsx @@ -1,12 +1,20 @@ 'use client'; -import { SiteAds, SiteAdsStatus } from '@gitbook/api'; +import { + SiteAds, + SiteAdsStatus, + SiteInsightsAdPlacement, + SiteInsightsAd, + SiteInsightsTrademarkPlacement, +} from '@gitbook/api'; import * as React from 'react'; import { t, useLanguage } from '@/intl/client'; import { ClassValue, tcls } from '@/lib/tailwind'; import { renderAd } from './renderAd'; +import { useTrackEvent } from '../Insights'; +import { Link } from '../primitives'; /** * Zone ID provided by BuySellAds for the preview. @@ -28,7 +36,7 @@ export function Ad({ }: { zoneId: string | null; spaceId: string; - placement: string; + placement: SiteInsightsAdPlacement; ignore: boolean; style?: ClassValue; siteAdsStatus?: SiteAds['status']; @@ -36,7 +44,20 @@ export function Ad({ }) { const containerRef = React.useRef(null); const [visible, setVisible] = React.useState(false); - const [ad, setAd] = React.useState(undefined); + const [ad, setAd] = React.useState< + { children: React.ReactNode; insightsAd: SiteInsightsAd | null } | undefined + >(undefined); + const trackEvent = useTrackEvent(); + + // Track display of the ad + React.useEffect(() => { + if (ad?.insightsAd) { + trackEvent({ + type: 'ad_display', + ad: ad.insightsAd, + }); + } + }, [ad]); // Observe the container visibility React.useEffect(() => { @@ -121,7 +142,7 @@ export function Ad({
{ad ? ( <> - {ad} + {ad.children} ) : null} @@ -132,6 +153,7 @@ export function Ad({ function AdSponsoredLink(props: { spaceId: string }) { const { spaceId } = props; const language = useLanguage(); + const trackEvent = useTrackEvent(); const viaUrl = new URL('https://www.gitbook.com'); viaUrl.searchParams.set('utm_source', 'content'); @@ -149,9 +171,17 @@ function AdSponsoredLink(props: { spaceId: string }) { 'dark:text-light/5', )} > - + {t(language, 'sponsored_via_gitbook')} - +

); } diff --git a/packages/gitbook/src/components/Ads/AdClassicRendering.tsx b/packages/gitbook/src/components/Ads/AdClassicRendering.tsx index dc2859a5b..3673f82e3 100644 --- a/packages/gitbook/src/components/Ads/AdClassicRendering.tsx +++ b/packages/gitbook/src/components/Ads/AdClassicRendering.tsx @@ -1,20 +1,38 @@ +import { SiteInsightsAd } from '@gitbook/api'; import * as React from 'react'; import { getResizedImageURL } from '@/lib/images'; import { tcls } from '@/lib/tailwind'; import { AdItem } from './types'; +import { Link } from '../primitives'; /** * Classic rendering for an ad. */ -export async function AdClassicRendering({ ad }: { ad: AdItem }) { +export async function AdClassicRendering({ + ad, + insightsAd, +}: { + ad: AdItem; + insightsAd: SiteInsightsAd | null; +}) { const smallImgSrc = 'smallImage' in ad ? await getResizedImageURL(ad.smallImage, { width: 192, dpr: 2 }) : null; const logoSrc = 'logo' in ad ? await getResizedImageURL(ad.logo, { width: 192 - 48, dpr: 2 }) : null; return ( - {smallImgSrc && 'smallImage' in ad ? (
@@ -47,6 +63,6 @@ export async function AdClassicRendering({ ad }: { ad: AdItem }) {
{ad.description}
-
+ ); } diff --git a/packages/gitbook/src/components/Ads/AdCoverRendering.tsx b/packages/gitbook/src/components/Ads/AdCoverRendering.tsx index e5d8d1c47..5a78e61e4 100644 --- a/packages/gitbook/src/components/Ads/AdCoverRendering.tsx +++ b/packages/gitbook/src/components/Ads/AdCoverRendering.tsx @@ -1,3 +1,4 @@ +import { SiteInsightsAd } from '@gitbook/api'; import * as React from 'react'; import { hexToRgba } from '@/lib/colors'; @@ -5,15 +6,32 @@ import { getResizedImageURL } from '@/lib/images'; import { tcls } from '@/lib/tailwind'; import { AdCover } from './types'; +import { Link } from '../primitives'; /** * Cover rendering for an ad. */ -export async function AdCoverRendering({ ad }: { ad: AdCover }) { +export async function AdCoverRendering({ + ad, + insightsAd, +}: { + ad: AdCover; + insightsAd: SiteInsightsAd | null; +}) { const largeImage = await getResizedImageURL(ad.largeImage, { width: 128, dpr: 2 }); return ( -
- + ); } diff --git a/packages/gitbook/src/components/Ads/renderAd.tsx b/packages/gitbook/src/components/Ads/renderAd.tsx index 63699bcf6..a02c20d92 100644 --- a/packages/gitbook/src/components/Ads/renderAd.tsx +++ b/packages/gitbook/src/components/Ads/renderAd.tsx @@ -1,5 +1,6 @@ 'use server'; +import { SiteInsightsAd, SiteInsightsAdPlacement } from '@gitbook/api'; import { headers } from 'next/headers'; import { AdClassicRendering } from './AdClassicRendering'; @@ -20,7 +21,7 @@ interface FetchLiveAdOptions { /** Mode to render the Ad */ mode: 'classic' | 'auto' | 'cover'; /** Name of the placement for the ad */ - placement: string; + placement: SiteInsightsAdPlacement; /** If true, we'll not track it as an impression */ ignore: boolean; } @@ -47,16 +48,28 @@ export async function renderAd(options: FetchAdOptions) { const { ad } = result; - return ( - <> - {mode === 'classic' || !('callToAction' in ad) ? ( - - ) : ( - - )} - {ad.pixel ? : null} - - ); + const insightsAd: SiteInsightsAd | null = + options.source === 'live' + ? { + placement: options.placement, + zoneId: options.zoneId, + domain: 'company' in ad ? ad.company : '', + } + : null; + + return { + children: ( + <> + {mode === 'classic' || !('callToAction' in ad) ? ( + + ) : ( + + )} + {ad.pixel ? : null} + + ), + insightsAd, + }; } async function fetchAd({ diff --git a/packages/gitbook/src/components/DocumentView/BlockContentRef.tsx b/packages/gitbook/src/components/DocumentView/BlockContentRef.tsx index 228207a25..d928de7fa 100644 --- a/packages/gitbook/src/components/DocumentView/BlockContentRef.tsx +++ b/packages/gitbook/src/components/DocumentView/BlockContentRef.tsx @@ -35,8 +35,11 @@ export async function BlockContentRef(props: BlockProps title={resolved.text} style={style} insights={{ - target: block.data.ref, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: block.data.ref, + position: SiteInsightsLinkPosition.Content, + }, }} /> ); diff --git a/packages/gitbook/src/components/DocumentView/File.tsx b/packages/gitbook/src/components/DocumentView/File.tsx index 923e35f38..8c78bd2bc 100644 --- a/packages/gitbook/src/components/DocumentView/File.tsx +++ b/packages/gitbook/src/components/DocumentView/File.tsx @@ -26,8 +26,11 @@ export async function File(props: BlockProps) { href={file.downloadURL} download={file.name} insights={{ - target: block.data.ref, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: block.data.ref, + position: SiteInsightsLinkPosition.Content, + }, }} className={tcls( 'group/file', diff --git a/packages/gitbook/src/components/DocumentView/InlineLink.tsx b/packages/gitbook/src/components/DocumentView/InlineLink.tsx index ebe9b0e66..6f0262e0f 100644 --- a/packages/gitbook/src/components/DocumentView/InlineLink.tsx +++ b/packages/gitbook/src/components/DocumentView/InlineLink.tsx @@ -27,8 +27,11 @@ export async function InlineLink(props: InlineProps) { href={resolved.href} className="underline underline-offset-2 text-primary hover:text-primary-700 transition-colors" insights={{ - target: inline.data.ref, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: inline.data.ref, + position: SiteInsightsLinkPosition.Content, + }, }} > ) { {resolved.text} diff --git a/packages/gitbook/src/components/DocumentView/Table/RecordCard.tsx b/packages/gitbook/src/components/DocumentView/Table/RecordCard.tsx index 5edb42142..4e14c7758 100644 --- a/packages/gitbook/src/components/DocumentView/Table/RecordCard.tsx +++ b/packages/gitbook/src/components/DocumentView/Table/RecordCard.tsx @@ -166,8 +166,11 @@ export async function RecordCard( 'dark:hover:before:ring-light/4', ])} insights={{ - target: targetRef, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: targetRef, + position: SiteInsightsLinkPosition.Content, + }, }} > {body} diff --git a/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx b/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx index fae743b2b..e525499f9 100644 --- a/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx +++ b/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx @@ -168,11 +168,14 @@ export async function RecordColumnValue( insights={ ref.file ? { - target: { - kind: 'file', - file: ref.file.id, + type: 'link_click', + link: { + target: { + kind: 'file', + file: ref.file.id, + }, + position: SiteInsightsLinkPosition.Content, }, - position: SiteInsightsLinkPosition.Content, } : undefined } @@ -225,8 +228,11 @@ export async function RecordColumnValue( insights={ contentRef ? { - target: contentRef, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: contentRef, + position: SiteInsightsLinkPosition.Content, + }, } : undefined } @@ -260,8 +266,11 @@ export async function RecordColumnValue( key={index} href={resolved.href} insights={{ - target: contentRef, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: contentRef, + position: SiteInsightsLinkPosition.Content, + }, }} > {resolved.text} diff --git a/packages/gitbook/src/components/Footer/FooterLinksGroup.tsx b/packages/gitbook/src/components/Footer/FooterLinksGroup.tsx index bcb12615e..20096b980 100644 --- a/packages/gitbook/src/components/Footer/FooterLinksGroup.tsx +++ b/packages/gitbook/src/components/Footer/FooterLinksGroup.tsx @@ -54,8 +54,11 @@ async function FooterLink(props: { link: CustomizationContentLink; context: Cont 'underline-offset-2', )} insights={{ - target: link.to, - position: SiteInsightsLinkPosition.Footer, + type: 'link_click', + link: { + target: link.to, + position: SiteInsightsLinkPosition.Footer, + }, }} > {link.title} diff --git a/packages/gitbook/src/components/Header/HeaderLink.tsx b/packages/gitbook/src/components/Header/HeaderLink.tsx index f844c86ee..3a979d8e0 100644 --- a/packages/gitbook/src/components/Header/HeaderLink.tsx +++ b/packages/gitbook/src/components/Header/HeaderLink.tsx @@ -145,8 +145,11 @@ function HeaderItemButton( }[linkStyle], )} insights={{ - target: linkTarget, - position: SiteInsightsLinkPosition.Header, + type: 'link_click', + link: { + target: linkTarget, + position: SiteInsightsLinkPosition.Header, + }, }} {...rest} > @@ -175,8 +178,11 @@ function HeaderItemLink(props: Omit) { href={href} className={getHeaderLinkClassName({ headerPreset })} insights={{ - target: linkTarget, - position: SiteInsightsLinkPosition.Header, + type: 'link_click', + link: { + target: linkTarget, + position: SiteInsightsLinkPosition.Header, + }, }} {...rest} > @@ -219,7 +225,13 @@ async function SubHeaderLink(props: { return ( {link.title} diff --git a/packages/gitbook/src/components/Header/HeaderLinkMore.tsx b/packages/gitbook/src/components/Header/HeaderLinkMore.tsx index e6a3f6b6b..1e31fc938 100644 --- a/packages/gitbook/src/components/Header/HeaderLinkMore.tsx +++ b/packages/gitbook/src/components/Header/HeaderLinkMore.tsx @@ -82,8 +82,11 @@ async function MoreMenuLink(props: { insights={ link.to ? { - target: link.to, - position: SiteInsightsLinkPosition.Header, + type: 'link_click', + link: { + target: link.to, + position: SiteInsightsLinkPosition.Header, + }, } : undefined } diff --git a/packages/gitbook/src/components/Insights/InsightsProvider.tsx b/packages/gitbook/src/components/Insights/InsightsProvider.tsx index 2e65ab8c5..86ca87a2a 100644 --- a/packages/gitbook/src/components/Insights/InsightsProvider.tsx +++ b/packages/gitbook/src/components/Insights/InsightsProvider.tsx @@ -10,7 +10,7 @@ import * as cookies from '@/lib/cookies'; import { getSession } from './sessions'; import { getVisitorId } from './visitorId'; -type SiteEventName = api.SiteInsightsEvent['type']; +export type InsightsEventName = api.SiteInsightsEvent['type']; /** * Global context for all events in the session. @@ -46,15 +46,14 @@ interface InsightsEventOptions { /** * Input data for an event. */ -type TrackEventInput = { type: EventName } & Omit< - Extract, - 'location' | 'session' ->; +export type TrackEventInput = { + type: EventName; +} & Omit, 'location' | 'session'>; /** * Callback to track an event. */ -type TrackEventCallback = ( +type TrackEventCallback = ( event: TrackEventInput, ctx?: InsightsEventPageContext, options?: InsightsEventOptions, @@ -80,7 +79,7 @@ export function InsightsProvider(props: InsightsProviderProps) { [pathname: string]: | { url: string; - events: TrackEventInput[]; + events: TrackEventInput[]; context: InsightsEventContext; pageContext?: InsightsEventPageContext; } @@ -152,7 +151,7 @@ export function InsightsProvider(props: InsightsProviderProps) { const trackEvent: TrackEventCallback = useEventCallback( ( - event: TrackEventInput, + event: TrackEventInput, ctx?: InsightsEventPageContext, options?: InsightsEventOptions, ) => { @@ -253,7 +252,7 @@ function sendEvents(args: { */ function transformEvents(input: { url: string; - events: TrackEventInput[]; + events: TrackEventInput[]; context: InsightsEventContext; pageContext: InsightsEventPageContext; visitorId: string; diff --git a/packages/gitbook/src/components/PageAside/PageAside.tsx b/packages/gitbook/src/components/PageAside/PageAside.tsx index 64e686ad1..696ba4196 100644 --- a/packages/gitbook/src/components/PageAside/PageAside.tsx +++ b/packages/gitbook/src/components/PageAside/PageAside.tsx @@ -5,6 +5,7 @@ import { Site, SiteAdsStatus, SiteCustomizationSettings, + SiteInsightsAdPlacement, Space, } from '@gitbook/api'; import { Icon } from '@gitbook/icons'; @@ -226,7 +227,7 @@ export async function PageAside(props: { zoneId={ site?.ads && site.ads.status === SiteAdsStatus.Live ? site.ads.zoneId : null } - placement="page.aside" + placement={SiteInsightsAdPlacement.Aside} spaceId={space.id} siteAdsStatus={site?.ads && site.ads.status ? site.ads.status : undefined} ignore={process.env.NODE_ENV !== 'production'} diff --git a/packages/gitbook/src/components/PageBody/PageBodyBlankslate.tsx b/packages/gitbook/src/components/PageBody/PageBodyBlankslate.tsx index 1e8455628..5bdf4fbc6 100644 --- a/packages/gitbook/src/components/PageBody/PageBodyBlankslate.tsx +++ b/packages/gitbook/src/components/PageBody/PageBodyBlankslate.tsx @@ -52,8 +52,11 @@ export async function PageBodyBlankslate(props: { title={child.title} href={resolved.href} insights={{ - target: child.target, - position: SiteInsightsLinkPosition.Content, + type: 'link_click', + link: { + target: child.target, + position: SiteInsightsLinkPosition.Content, + }, }} /> ); diff --git a/packages/gitbook/src/components/PageBody/PageFooterNavigation.tsx b/packages/gitbook/src/components/PageBody/PageFooterNavigation.tsx index 32fc2b860..1163514a5 100644 --- a/packages/gitbook/src/components/PageBody/PageFooterNavigation.tsx +++ b/packages/gitbook/src/components/PageBody/PageFooterNavigation.tsx @@ -51,11 +51,14 @@ export async function PageFooterNavigation(props: { title={previous.title} href={previousHref} insights={{ - target: { - kind: 'page', - page: previous.id, + type: 'link_click', + link: { + target: { + kind: 'page', + page: previous.id, + }, + position: SiteInsightsLinkPosition.Content, }, - position: SiteInsightsLinkPosition.Content, }} reversed /> @@ -67,11 +70,14 @@ export async function PageFooterNavigation(props: { title={next.title} href={nextHref} insights={{ - target: { - kind: 'page', - page: next.id, + type: 'link_click', + link: { + target: { + kind: 'page', + page: next.id, + }, + position: SiteInsightsLinkPosition.Content, }, - position: SiteInsightsLinkPosition.Content, }} /> ) : null} diff --git a/packages/gitbook/src/components/TableOfContents/PageDocumentItem.tsx b/packages/gitbook/src/components/TableOfContents/PageDocumentItem.tsx index 1c7236c6e..1e89e7cb5 100644 --- a/packages/gitbook/src/components/TableOfContents/PageDocumentItem.tsx +++ b/packages/gitbook/src/components/TableOfContents/PageDocumentItem.tsx @@ -29,11 +29,14 @@ export async function PageDocumentItem(props: { href={href} pathname={getPagePath(rootPages, page)} insights={{ - target: { - kind: 'page', - page: page.id, + type: 'link_click', + link: { + target: { + kind: 'page', + page: page.id, + }, + position: SiteInsightsLinkPosition.Sidebar, }, - position: SiteInsightsLinkPosition.Sidebar, }} descendants={ page.pages && page.pages.length ? ( diff --git a/packages/gitbook/src/components/TableOfContents/PageLinkItem.tsx b/packages/gitbook/src/components/TableOfContents/PageLinkItem.tsx index 37957cbc0..9b11da895 100644 --- a/packages/gitbook/src/components/TableOfContents/PageLinkItem.tsx +++ b/packages/gitbook/src/components/TableOfContents/PageLinkItem.tsx @@ -36,8 +36,11 @@ export async function PageLinkItem(props: { page: RevisionPageLink; context: Con 'dark:hover:bg-light/2', )} insights={{ - target: page.target, - position: SiteInsightsLinkPosition.Sidebar, + type: 'link_click', + link: { + target: page.target, + position: SiteInsightsLinkPosition.Sidebar, + }, }} > diff --git a/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx b/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx index d549c3758..275ca7884 100644 --- a/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx +++ b/packages/gitbook/src/components/TableOfContents/TableOfContents.tsx @@ -4,6 +4,7 @@ import { RevisionPageDocument, RevisionPageGroup, SiteCustomizationSettings, + SiteInsightsTrademarkPlacement, Space, } from '@gitbook/api'; import React from 'react'; @@ -135,7 +136,11 @@ export function TableOfContents(props: { )} /> {customization.trademark.enabled ? ( - + ) : null}
diff --git a/packages/gitbook/src/components/TableOfContents/Trademark.tsx b/packages/gitbook/src/components/TableOfContents/Trademark.tsx index 626826350..327f935aa 100644 --- a/packages/gitbook/src/components/TableOfContents/Trademark.tsx +++ b/packages/gitbook/src/components/TableOfContents/Trademark.tsx @@ -1,15 +1,23 @@ -import { CustomizationSettings, SiteCustomizationSettings, Space } from '@gitbook/api'; +import { + CustomizationSettings, + SiteCustomizationSettings, + Space, + SiteInsightsTrademarkPlacement, +} from '@gitbook/api'; import { Icon } from '@gitbook/icons'; import { t, getSpaceLanguage } from '@/intl/server'; import { tcls } from '@/lib/tailwind'; +import { Link } from '../primitives'; + /** * Trademark link to the GitBook. */ export function Trademark(props: { space: Space; customization: CustomizationSettings | SiteCustomizationSettings; + placement: SiteInsightsTrademarkPlacement; }) { return (
{t(language, 'powered_by_gitbook')} - + ); } diff --git a/packages/gitbook/src/components/primitives/Link.tsx b/packages/gitbook/src/components/primitives/Link.tsx index d39ffa09d..837894fcb 100644 --- a/packages/gitbook/src/components/primitives/Link.tsx +++ b/packages/gitbook/src/components/primitives/Link.tsx @@ -1,10 +1,9 @@ 'use client'; -import * as api from '@gitbook/api'; import NextLink, { LinkProps as NextLinkProps } from 'next/link'; import React from 'react'; -import { useTrackEvent } from '../Insights'; +import { useTrackEvent, TrackEventInput } from '../Insights'; // Props from Next, which includes NextLinkProps and all the things anchor elements support. type BaseLinkProps = Omit, keyof NextLinkProps> & @@ -13,8 +12,11 @@ type BaseLinkProps = Omit, keyof N } & React.RefAttributes; export type LinkInsightsProps = { - /** Target of the link, for insights. */ - insights?: api.SiteInsightsEventLinkClick['link']; + /** Event to track when the link is clicked. */ + insights?: + | TrackEventInput<'ad_click'> + | TrackEventInput<'link_click'> + | TrackEventInput<'trademark_click'>; }; export type LinkProps = Omit & @@ -40,7 +42,7 @@ export const Link = React.forwardRef(function Link( const onClick = (event: React.MouseEvent) => { if (insights) { - trackEvent({ type: 'link_click', link: insights }, undefined, { + trackEvent(insights, undefined, { immediate: isExternal, }); } diff --git a/packages/react-contentkit/package.json b/packages/react-contentkit/package.json index a4eb3c448..e47c9c241 100644 --- a/packages/react-contentkit/package.json +++ b/packages/react-contentkit/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "classnames": "^2.5.1", - "@gitbook/api": "^0.85.0", + "@gitbook/api": "^0.89.0", "assert-never": "^1.2.1" }, "peerDependencies": {