feat(analytics): add OpenPanel tracking to storefront
Add comprehensive OpenPanel analytics tracking: - Install @openpanel/nextjs SDK - Add OpenPanelComponent to root layout for automatic page views - Create useAnalytics hook for tracking custom events - Track checkout funnel: started, shipping step, order completed - Track product views and add-to-cart events - Identify users on order completion - Add NEXT_PUBLIC_OPENPANEL_CLIENT_ID to environment
This commit is contained in:
@@ -20,6 +20,7 @@ import BeforeAfterGallery from "@/components/home/BeforeAfterGallery";
|
||||
import HowItWorks from "@/components/home/HowItWorks";
|
||||
import NewsletterSection from "@/components/home/NewsletterSection";
|
||||
import BundleSelector from "@/components/product/BundleSelector";
|
||||
import { useAnalytics } from "@/lib/analytics";
|
||||
|
||||
interface ProductDetailProps {
|
||||
product: Product;
|
||||
@@ -99,8 +100,25 @@ export default function ProductDetail({ product, relatedProducts, bundleProducts
|
||||
const [urgencyIndex, setUrgencyIndex] = useState(0);
|
||||
const [selectedBundleVariantId, setSelectedBundleVariantId] = useState<string | null>(null);
|
||||
const { addLine, openCart } = useSaleorCheckoutStore();
|
||||
const { trackProductView, trackAddToCart } = useAnalytics();
|
||||
const validLocale = isValidLocale(locale) ? locale : "sr";
|
||||
|
||||
// Track product view on mount
|
||||
useEffect(() => {
|
||||
const localized = getLocalizedProduct(product, locale);
|
||||
const baseVariant = product.variants?.[0];
|
||||
const price = baseVariant?.pricing?.price?.gross?.amount || 0;
|
||||
const currency = baseVariant?.pricing?.price?.gross?.currency || "RSD";
|
||||
|
||||
trackProductView({
|
||||
id: product.id,
|
||||
name: localized.name,
|
||||
price,
|
||||
currency,
|
||||
category: product.category?.name,
|
||||
});
|
||||
}, [product, locale]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setUrgencyIndex(prev => (prev + 1) % 3);
|
||||
@@ -132,6 +150,25 @@ export default function ProductDetail({ product, relatedProducts, bundleProducts
|
||||
setIsAdding(true);
|
||||
try {
|
||||
await addLine(selectedVariantId, 1);
|
||||
|
||||
// Track add to cart
|
||||
const localized = getLocalizedProduct(product, locale);
|
||||
const baseVariant = product.variants?.[0];
|
||||
const selectedVariant = selectedVariantId === baseVariant?.id
|
||||
? baseVariant
|
||||
: bundleProducts.find(p => p.variants?.[0]?.id === selectedVariantId)?.variants?.[0];
|
||||
const price = selectedVariant?.pricing?.price?.gross?.amount || 0;
|
||||
const currency = selectedVariant?.pricing?.price?.gross?.currency || "RSD";
|
||||
|
||||
trackAddToCart({
|
||||
id: product.id,
|
||||
name: localized.name,
|
||||
price,
|
||||
currency,
|
||||
quantity: 1,
|
||||
variant: selectedVariant?.name,
|
||||
});
|
||||
|
||||
openCart();
|
||||
} finally {
|
||||
setIsAdding(false);
|
||||
|
||||
Reference in New Issue
Block a user