feat: integrate Rybbit analytics alongside OpenPanel
Some checks failed
Build and Deploy / build (push) Has been cancelled

- Add RybbitService for tracking e-commerce events
- Update useAnalytics hook to track with both OpenPanel and Rybbit
- Add Rybbit script to layout for page view tracking
- Track all applicable store events: product views, cart, checkout, orders, search, etc.
This commit is contained in:
Unchained
2026-03-31 00:38:38 +02:00
parent 044aefae94
commit b3efebd3e4
11 changed files with 1422 additions and 118 deletions

View File

@@ -0,0 +1,209 @@
"use client";
// Rybbit Analytics Service
// Self-hosted instance at rybbit.nodecrew.me
declare global {
interface Window {
rybbit?: {
event: (eventName: string, eventData?: Record<string, any>) => void;
pageview: () => void;
};
}
}
export const RYBBIT_HOST = "https://rybbit.nodecrew.me";
export const RYBBIT_SITE_ID = "1";
/**
* Check if Rybbit is loaded and available
*/
export function isRybbitAvailable(): boolean {
return typeof window !== "undefined" &&
!!window.rybbit &&
typeof window.rybbit.event === "function";
}
/**
* Track a custom event with Rybbit
*/
export function trackRybbitEvent(
eventName: string,
eventData?: Record<string, any>
): void {
if (isRybbitAvailable()) {
try {
window.rybbit!.event(eventName, eventData);
} catch (e) {
console.warn("[Rybbit] Event tracking error:", e);
}
} else {
console.warn("[Rybbit] Not available for event:", eventName);
}
}
/**
* Track page view manually (usually auto-tracked by Rybbit script)
*/
export function trackRybbitPageview(): void {
if (isRybbitAvailable()) {
try {
window.rybbit!.pageview();
} catch (e) {
console.warn("[Rybbit] Pageview error:", e);
}
}
}
// E-commerce Event Tracking Functions
export function trackRybbitProductView(product: {
id: string;
name: string;
price: number;
currency: string;
category?: string;
variant?: string;
}): void {
trackRybbitEvent("product_view", {
product_id: product.id,
product_name: product.name,
price: product.price,
currency: product.currency,
category: product.category,
variant: product.variant,
});
}
export function trackRybbitAddToCart(product: {
id: string;
name: string;
price: number;
currency: string;
quantity: number;
variant?: string;
}): void {
trackRybbitEvent("add_to_cart", {
product_id: product.id,
product_name: product.name,
price: product.price,
currency: product.currency,
quantity: product.quantity,
variant: product.variant,
});
}
export function trackRybbitRemoveFromCart(product: {
id: string;
name: string;
quantity: number;
}): void {
trackRybbitEvent("remove_from_cart", {
product_id: product.id,
product_name: product.name,
quantity: product.quantity,
});
}
export function trackRybbitCartView(cart: {
total: number;
currency: string;
item_count: number;
}): void {
trackRybbitEvent("cart_view", {
cart_total: cart.total,
currency: cart.currency,
item_count: cart.item_count,
});
}
export function trackRybbitCheckoutStarted(cart: {
total: number;
currency: string;
item_count: number;
items: Array<{
id: string;
name: string;
quantity: number;
price: number;
}>;
}): void {
trackRybbitEvent("checkout_started", {
cart_total: cart.total,
currency: cart.currency,
item_count: cart.item_count,
items: cart.items,
});
}
export function trackRybbitCheckoutStep(step: string, data?: Record<string, unknown>): void {
trackRybbitEvent("checkout_step", {
step,
...data,
});
}
export function trackRybbitOrderCompleted(order: {
order_id: string;
order_number: string;
total: number;
currency: string;
item_count: number;
shipping_cost?: number;
customer_email?: string;
payment_method?: string;
}): void {
trackRybbitEvent("order_completed", {
order_id: order.order_id,
order_number: order.order_number,
total: order.total,
currency: order.currency,
item_count: order.item_count,
shipping_cost: order.shipping_cost,
customer_email: order.customer_email,
payment_method: order.payment_method,
});
}
export function trackRybbitSearch(query: string, results_count: number): void {
trackRybbitEvent("search", {
query,
results_count,
});
}
export function trackRybbitExternalLink(url: string, label?: string): void {
trackRybbitEvent("external_link_click", {
url,
label,
});
}
export function trackRybbitNewsletterSignup(email: string, source: string): void {
trackRybbitEvent("newsletter_signup", {
email,
source,
});
}
export function trackRybbitWishlistAdd(product: {
id: string;
name: string;
}): void {
trackRybbitEvent("wishlist_add", {
product_id: product.id,
product_name: product.name,
});
}
export function trackRybbitUserLogin(method: string): void {
trackRybbitEvent("user_login", {
method,
});
}
export function trackRybbitUserRegister(method: string): void {
trackRybbitEvent("user_register", {
method,
});
}