Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 45 additions & 19 deletions src/components/Stream.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ interface Props {
moreVideosLink: string;
}

const { videoId, videoTitle, thumbnailTimeOrURL, moreVideosLink="true" } = Astro.props;
const {
videoId,
videoTitle,
thumbnailTimeOrURL,
moreVideosLink = "true",
} = Astro.props;

const customerId = "1mwganm1ma0xgnmj";
const baseUrl = `https://customer-${customerId}.cloudflarestream.com/`;
Expand All @@ -32,25 +37,46 @@ if (thumbnailTimeOrURL !== undefined) {
}
---

<div style="position: relative; padding-top: 56.25%">
<iframe
src={url.toString()}
style="border: none; position: absolute; top: 0; left: 0; height: 100%; width: 100%;"
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
allowfullscreen="true"
title={videoTitle}
id={videoId}></iframe>
</div>

{moreVideosLink=="true" &&
<a href="https://www.youtube.com/@CloudflareDevelopers" target="_blank">Watch more videos on our Developer Channel</a>
}
<stream-player data-id={videoId} data-title={videoTitle}>
<div style="position: relative; padding-top: 56.25%">
<iframe
src={url.toString()}
style="border: none; position: absolute; top: 0; left: 0; height: 100%; width: 100%;"
allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
allowfullscreen="true"
title={videoTitle}
id={videoId}></iframe>
</div>

{
moreVideosLink == "true" && (
<a href="https://www.youtube.com/@CloudflareDevelopers" target="_blank">
Watch more videos on our Developer Channel
</a>
)
}
</stream-player>

<script is:inline src="https://embed.cloudflarestream.com/embed/sdk.latest.js"
></script>
<script is:inline define:vars={{ vidId: videoId, videoTitle }}>
const video = document.getElementById(vidId);
Stream(video).addEventListener("play", () => {
zaraz.track("play docs video", { title: videoTitle });
});

<script>
import { track } from "~/util/zaraz";

declare function Stream(player: HTMLIFrameElement): HTMLVideoElement;

class StreamPlayer extends HTMLElement {
connectedCallback() {
const id = CSS.escape(this.dataset.id as string);
const title = this.dataset.title as string;

const player = this.querySelector(`#${id}`) as HTMLIFrameElement;

Stream(player).addEventListener("play", () => {
track("play docs video", { title: title });
});
}
}

customElements.define("stream-player", StreamPlayer);
</script>
44 changes: 8 additions & 36 deletions src/scripts/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,9 @@
const links = document.querySelectorAll<HTMLAnchorElement>("a");
import { registerLinks } from "./analytics/links";
import { registerTabs } from "./analytics/tabs";
import { registerDetails } from "./analytics/details";
import { registerCopyButtons } from "./analytics/codeblocks";

function $zarazLinkEvent(type: string, link: HTMLAnchorElement) {
// @ts-expect-error TODO: type zaraz
zaraz.track(type, { href: link.href, hostname: link.hostname });
}
function registerLinkAnalytics() {
if (!links || links.length === 0) {
return;
}
for (const link of links) {
if (!link.href) {
continue;
}
const linkURL = new URL(link.href);
const cfSubdomainRegex = new RegExp(`^[^.]+?\\.cloudflare\\.com`);
if (linkURL.hostname !== "developers.cloudflare.com") {
if (
linkURL.hostname === "workers.cloudflare.com" &&
linkURL.pathname.startsWith("/playground#")
) {
link.addEventListener("click", () => {
$zarazLinkEvent("playground link click", link);
});
} else if (cfSubdomainRegex.test(linkURL.hostname)) {
link.addEventListener("click", () => {
$zarazLinkEvent("Cross Domain Click", link);
});
} else {
link.addEventListener("click", () => {
$zarazLinkEvent("external link click", link);
});
}
}
}
}
registerLinkAnalytics();
registerLinks();
registerTabs();
registerDetails();
registerCopyButtons();
34 changes: 34 additions & 0 deletions src/scripts/analytics/codeblocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { track } from "~/util/zaraz";

export function registerCopyButtons() {
const elements = document.querySelectorAll<HTMLElement>(
".expressive-code > figure.frame",
);

if (!elements || elements.length === 0) {
return;
}

for (const el of elements) {
const hasTitle = el.classList.contains("has-title");

const title = hasTitle
? el.querySelector<HTMLElement>(".header")?.innerText
: "title not set";

const language =
el.querySelector<HTMLPreElement>("pre")?.dataset.language ??
"language not set";

const button = el.querySelector<HTMLButtonElement>(".copy > button");

if (!button) continue;

button.addEventListener("click", () => {
track("copy button link click", {
title,
language,
});
});
}
}
20 changes: 20 additions & 0 deletions src/scripts/analytics/details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { track } from "~/util/zaraz";

export function registerDetails() {
const elements = document.querySelectorAll<HTMLDetailsElement>("details");

if (!elements || elements.length === 0) {
return;
}

for (const el of elements) {
const summary = el.querySelector("summary");

if (!summary) continue;

el.addEventListener("toggle", () => {
if (!el.open) return;
track("dropdown click", { text: summary.innerText });
});
}
}
38 changes: 38 additions & 0 deletions src/scripts/analytics/links.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { track } from "~/util/zaraz";

function registerLink(type: string, link: HTMLAnchorElement) {
link.addEventListener("click", () => {
track(type, { href: link.href, hostname: link.hostname });
});
}

export function registerLinks() {
const elements = document.querySelectorAll<HTMLAnchorElement>("a[href]");

if (!elements || elements.length === 0) {
return;
}

for (const el of elements) {
const { hostname, pathname } = new URL(el.href);

if (hostname === "developers.cloudflare.com" || hostname === "localhost") {
continue;
}

if (
hostname === "workers.cloudflare.com" &&
pathname.startsWith("/playground#")
) {
registerLink("playground link click", el);
continue;
}

if (hostname.endsWith(".cloudflare.com")) {
registerLink("Cross Domain Click", el);
continue;
}

registerLink("external link click", el);
}
}
17 changes: 17 additions & 0 deletions src/scripts/analytics/tabs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { track } from "~/util/zaraz";

export function registerTabs() {
const elements = document.querySelectorAll<HTMLAnchorElement>(
"starlight-tabs a[role='tab']",
);

if (!elements || elements.length === 0) {
return;
}

elements.forEach((el) =>
el.addEventListener("click", () => {
track("tab click", { selected_option: el.innerText });
}),
);
}
18 changes: 18 additions & 0 deletions src/util/zaraz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
declare global {
interface Window {
zaraz?: {
track: Track;
};
}
}

type Track = (event: string, properties?: Record<string, any>) => void;

export const track: Track = (event, properties) => {
if (!window.zaraz) {
console.log("zaraz.track:", event, properties);
return;
}

window.zaraz.track(event, properties);
};
Loading