From 658883c5fc5318325df8b8fd01400fb16f7e1736 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com> Date: Mon, 2 Nov 2026 16:34:14 -0600 Subject: [PATCH 1/2] feat(docs): tag Discord links and preserve social selection intent --- scripts/docs-site/analytics-behavior.test.mjs | 21 +++++++++++-------- scripts/docs-site/analytics-events.mjs | 3 ++- scripts/docs-site/build.mjs | 12 +++++------ scripts/docs-site/community-invite.test.mjs | 2 +- .../docs-site/discord-source-tags.test.mjs | 16 ++++++++++++++ scripts/docs-site/home-sections.mjs | 2 +- scripts/docs-site/preview-build.test.mjs | 4 +++- 7 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 scripts/docs-site/discord-source-tags.test.mjs diff --git a/scripts/docs-site/analytics-behavior.test.mjs b/scripts/docs-site/analytics-behavior.test.mjs index 3bdba94035..0d9df9802a 100644 --- a/scripts/docs-site/analytics-behavior.test.mjs +++ b/scripts/docs-site/analytics-behavior.test.mjs @@ -90,7 +90,7 @@ function wireEvents(collected) { test("selection placement and sanitized destination share one event without changing native clicks", async t => { const destination = "https://discord.com/invite/clawd"; const { page, context, events, collected } = await openSite(t, { - articleLinks: `\n[Community](${destination})\n\n[External reference](https://example.org/guide?ref=docs#intro)\n\n[Product](https://openclaw.ai/install?ref=docs#intro)\n`, + articleLinks: `\n[Community](${destination})\n\n[External reference](https://example.org/guide?ref=docs#intro)\n\n[Product](https://openclaw.ai/install?ref=docs#intro)\n\n[Redirect slash](https://openclaw.ai/discord/?from=docs-home-community&unknown=ignored#join)\n\n[Not Discord](https://openclaw.ai/discord-extra?from=docs-header)\n`, }); page.setDefaultTimeout(5000); // Abort only after observing native navigation so the fixture stays loaded. @@ -152,11 +152,14 @@ test("selection placement and sanitized destination share one event without chan } } } - for (const [selector, placement] of [[".community-invite", "community_invite"], [".site-footer", "footer"], [".doc", "article"]]) { - await clickAndObserve(`${selector} a[href="${destination}"]`, placement, "social_link", "discord", destination, true); + for (const [selector, placement, tag] of [[".site-header", "header", "docs-header"], [".community-invite", "community_invite", "docs-community-invite"], [".site-footer", "footer", "docs-footer"]]) { + await clickAndObserve(`${selector} a[href="https://openclaw.ai/discord?from=${tag}"]`, placement, "social_link", "discord", "https://openclaw.ai/discord"); } + await clickAndObserve(`.doc a[href="${destination}"]`, "article", "social_link", "discord", destination, true); + await clickAndObserve('.doc a[href^="https://openclaw.ai/discord/?"]', "article", "social_link", "discord", "https://openclaw.ai/discord/"); + await clickAndObserve('.doc a[href^="https://openclaw.ai/discord-extra"]', "article", "site_link", "openclaw.ai/discord-extra", "https://openclaw.ai/discord-extra"); await clickAndObserve('.doc a[href^="https://example.org/"]', "article", "public_reference", "https://example.org/guide", "https://example.org/guide"); - await clickAndObserve('.doc a[href^="https://openclaw.ai/"]', "article", "site_link", "openclaw.ai/install", "https://openclaw.ai/install"); + await clickAndObserve('.doc a[href^="https://openclaw.ai/install"]', "article", "site_link", "openclaw.ai/install", "https://openclaw.ai/install"); for (const label of ["Edit source", "Raise issue"]) { const link = page.getByRole("link", { name: label, exact: true }); const url = new URL(await link.getAttribute("href")); @@ -165,15 +168,15 @@ test("selection placement and sanitized destination share one event without chan } const beforePrivate = (await events("select_content")).length; - const nativeBeforePrivate = count("click", destination).length; + const nativeBeforePrivate = count("click", "https://openclaw.ai/discord").length; await page.locator("[data-chat-toggle]").click(); - await page.locator(`.site-footer a[href="${destination}"]`).click(); + await page.locator('.site-footer a[href="https://openclaw.ai/discord?from=docs-footer"]').click(); await page.waitForTimeout(1200); await page.locator("[data-chat-minimize]").click(); await page.waitForTimeout(1200); assert.equal((await events("select_content")).length, beforePrivate, "private selection is not replayed on close"); - assert.equal(count("click", destination).length, nativeBeforePrivate, "private native click is not replayed on close"); - await clickAndObserve(`.site-footer a[href="${destination}"]`, "footer", "social_link", "discord", destination, true); + assert.equal(count("click", "https://openclaw.ai/discord").length, nativeBeforePrivate, "private native click is not replayed on close"); + await clickAndObserve('.site-footer a[href="https://openclaw.ai/discord?from=docs-footer"]', "footer", "social_link", "discord", "https://openclaw.ai/discord"); }); test("selection destination stays absent for same-origin, non-anchor, unknown and blocked contexts", async t => { @@ -205,7 +208,7 @@ test("selection destination stays absent for same-origin, non-anchor, unknown an assert.equal((await events("select_content")).length, before); await setBrowserPrivacy(page, true); const requestsBefore = googleRequests.length; - await page.locator('.site-footer a[href="https://discord.com/invite/clawd"]').click(); + await page.locator('.site-footer a[href="https://openclaw.ai/discord?from=docs-footer"]').click(); await page.waitForTimeout(1200); await setBrowserPrivacy(page, false); assert.equal((await events("select_content")).length, before); diff --git a/scripts/docs-site/analytics-events.mjs b/scripts/docs-site/analytics-events.mjs index 1c4f5cca72..70ce54b3bf 100644 --- a/scripts/docs-site/analytics-events.mjs +++ b/scripts/docs-site/analytics-events.mjs @@ -220,7 +220,8 @@ export function createDocsAnalyticsEvents(analytics) { const destination = url.origin === window.location.origin ? {} : { link_url: url.origin + url.pathname, link_domain: url.hostname }; const artifact = artifactChoice(url); if (link.matches(".search-result")) flushSearch(); - if (socialHosts[url.hostname]) select("social_link", socialHosts[url.hostname], location, destination); + if (url.origin === "https://openclaw.ai" && /^\/discord\/?$/.test(url.pathname)) select("social_link", "discord", location, destination); + else if (socialHosts[url.hostname]) select("social_link", socialHosts[url.hostname], location, destination); else if (canonicalHosts.has(url.hostname) && !/\/ask-molty\/|\/__elements/i.test(url.pathname)) { select(link.matches(".search-result") ? "search_result" : artifact ? "download" : url.hostname === "docs.openclaw.ai" ? "documentation" : "site_link", url.hostname === "docs.openclaw.ai" ? url.pathname : url.hostname + url.pathname, location, { ...artifact, ...destination }); } else if (link.closest(".page-actions")) select("page_action", /chatgpt/.test(url.hostname) ? "ask_chatgpt" : /claude/.test(url.hostname) ? "ask_claude" : "view_markdown", location, destination); diff --git a/scripts/docs-site/build.mjs b/scripts/docs-site/build.mjs index 45e026ac0f..9e4a0faa94 100644 --- a/scripts/docs-site/build.mjs +++ b/scripts/docs-site/build.mjs @@ -405,7 +405,7 @@ function siteHeader(page) {
${escapeHtml(strings.communityBody)}
${escapeUiText(text)}
`).join('')}${escapeUiText(text)}
`).join('')}