Skip to content

Commit

Permalink
improve analytics events
Browse files Browse the repository at this point in the history
  • Loading branch information
tlgimenes committed Nov 7, 2023
1 parent bce0d50 commit b289107
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 107 deletions.
77 changes: 53 additions & 24 deletions components/Analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
import { sendEvent } from "$store/sdk/analytics.tsx";
import type { AnalyticsEvent } from "apps/commerce/types.ts";
import { scriptAsDataURI } from "apps/utils/dataURI.ts";

const snippet = (id: string, event: AnalyticsEvent) => {
const element = document.getElementById(id);

if (!element) {
return console.warn(
`Could not find element ${id}. Click event will not be send. This will cause loss in analytics`,
);
}

element.addEventListener("click", () => {
console.log(JSON.stringify(event, null, 2));
window.DECO.events.dispatch(event);
});
};

/**
* This function is usefull for sending events on click. Works with both Server and Islands components
*/
export const SendEventOnClick = <E extends AnalyticsEvent>({ event, id }: {
event: E;
id: string;
}) => <script defer src={scriptAsDataURI(snippet, id, event)} />;
}) => (
<script
defer
src={scriptAsDataURI(
(id: string, event: AnalyticsEvent) => {
const elem = document.getElementById(id);

/**
* This componente should be used when want to send event for rendered componentes.
* This behavior is usefull for view_* events.
*/
export const SendEventOnLoad = <E extends AnalyticsEvent>(
{ event }: { event: E; id?: string },
) => <script defer src={scriptAsDataURI(sendEvent, event)} />;
if (!elem) {
return console.warn(
`Could not find element ${id}. Click event will not be send. This will cause loss in analytics`,
);
}

elem.addEventListener("click", () => {
window.DECO.events.dispatch(event);
});
},
id,
event,
)}
/>
);

export const SendEventOnView = <E extends AnalyticsEvent>(
{ event, id }: { event: E; id: string },
) => (
<script
defer
src={scriptAsDataURI(
(id: string, event: E) => {
const elem = document.getElementById(id);

if (!elem) {
return console.warn(
`Could not find element ${id}. Click event will not be send. This will cause loss in analytics`,
);
}

const observer = new IntersectionObserver((items) => {
for (const item of items) {
if (!item.isIntersecting) continue;

window.DECO.events.dispatch(event);
observer.unobserve(elem);
}
});

observer.observe(elem);
},
id,
event,
)}
/>
);
8 changes: 6 additions & 2 deletions components/header/Buttons/Cart/vtex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import Button from "./common.tsx";

function CartButton() {
const { loading, cart } = useCart();
const { totalizers = [], items = [], marketingData, storePreferencesData } =
cart.value ?? {};
const {
totalizers = [],
items = [],
marketingData,
storePreferencesData,
} = cart.value ?? {};
const coupon = marketingData?.coupon ?? undefined;
const currency = storePreferencesData?.currencyCode ?? "BRL";
const total = totalizers.find((item) => item.id === "Items")?.value ?? 0;
Expand Down
6 changes: 3 additions & 3 deletions components/minicart/common/CartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ function CartItem(
await onUpdateQuantity(quantity, index);

if (analyticsItem) {
analyticsItem.quantity = diff;

sendEvent({
name: diff < 0 ? "remove_from_cart" : "add_to_cart",
params: { items: [analyticsItem] },
params: {
items: [{ ...analyticsItem, quantity: Math.abs(diff) }],
},
});
}
})}
Expand Down
2 changes: 1 addition & 1 deletion components/product/AddToCartButton/linx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type Props = Omit<BtnProps, "onAddItem"> & {
productGroupID: string;
};

function AddToCartButton({ productGroupID, productID }: Props) {
function AddToCartButton({ productGroupID, productID, eventParams }: Props) {
const { addItem } = useCart();

return (
Expand Down
1 change: 0 additions & 1 deletion components/product/AddToCartButton/wake.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useCart } from "apps/wake/hooks/useCart.ts";
import Button, { Props as BtnProps } from "./common.tsx";


export interface Props extends Omit<BtnProps, "onAddItem"> {
productID: string;
}
Expand Down
62 changes: 12 additions & 50 deletions components/product/ProductInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SendEventOnLoad } from "$store/components/Analytics.tsx";
import { SendEventOnView } from "$store/components/Analytics.tsx";
import Breadcrumb from "$store/components/ui/Breadcrumb.tsx";
import AddToCartButtonLinx from "$store/islands/AddToCartButton/linx.tsx";
import AddToCartButtonShopify from "$store/islands/AddToCartButton/shopify.tsx";
Expand All @@ -9,6 +9,7 @@ import OutOfStock from "$store/islands/OutOfStock.tsx";
import ShippingSimulation from "$store/islands/ShippingSimulation.tsx";
import WishlistButton from "$store/islands/WishlistButton.tsx";
import { formatPrice } from "$store/sdk/format.ts";
import { useId } from "$store/sdk/useId.ts";
import { useOffer } from "$store/sdk/useOffer.ts";
import { usePlatform } from "$store/sdk/usePlatform.tsx";
import { ProductDetailsPage } from "apps/commerce/types.ts";
Expand All @@ -29,6 +30,7 @@ interface Props {

function ProductInfo({ page, layout }: Props) {
const platform = usePlatform();
const id = useId();

if (page === null) {
throw new Error("Missing Product Details Page Info");
Expand All @@ -39,14 +41,12 @@ function ProductInfo({ page, layout }: Props) {
product,
} = page;
const {
url,
productID,
offers,
name = "",
gtin,
isVariantOf,
additionalProperty = [],
brand,
} = product;
const description = product.description || isVariantOf?.description;
const {
Expand All @@ -57,26 +57,21 @@ function ProductInfo({ page, layout }: Props) {
availability,
} = useOffer(offers);
const productGroupID = isVariantOf?.productGroupID ?? "";
const discount = price && listPrice ? listPrice - price : 0;
const breadcrumb = {
...breadcrumbList,
itemListElement: breadcrumbList?.itemListElement.slice(0, -1),
numberOfItems: breadcrumbList.numberOfItems - 1,
};

const eventItem = {
item_list_id: "product",
item_list_name: "Product",
...mapProductToAnalyticsItem({
product,
breadcrumbList: breadcrumb,
price,
listPrice,
}),
};
const eventItem = mapProductToAnalyticsItem({
product,
breadcrumbList: breadcrumb,
price,
listPrice,
});

return (
<div class="flex flex-col">
<div class="flex flex-col" id={id}>
<Breadcrumb itemListElement={breadcrumb.itemListElement} />
{/* Code and name */}
<div class="mt-4 sm:mt-8">
Expand Down Expand Up @@ -126,14 +121,7 @@ function ProductInfo({ page, layout }: Props) {
<>
<AddToCartButtonVTEX
eventParams={{ items: [eventItem] }}
url={url || ""}
name={name}
groupName={isVariantOf?.name ?? ""}
brand={brand?.name ?? ""}
productID={productID}
productGroupID={productGroupID}
price={price}
discount={discount}
seller={seller}
/>
<WishlistButton
Expand All @@ -146,54 +134,27 @@ function ProductInfo({ page, layout }: Props) {
{platform === "wake" && (
<AddToCartButtonWake
eventParams={{ items: [eventItem] }}
url={url || ""}
name={name}
groupName={isVariantOf?.name ?? ""}
brand={brand?.name ?? ""}
productID={productID}
productGroupID={productGroupID}
price={price}
discount={discount}
/>
)}
{platform === "linx" && (
<AddToCartButtonLinx
eventParams={{ items: [eventItem] }}
url={url || ""}
name={name}
groupName={isVariantOf?.name ?? ""}
brand={brand?.name ?? ""}
productID={productID}
productGroupID={productGroupID}
price={price}
discount={discount}
/>
)}
{platform === "vnda" && (
<AddToCartButtonVNDA
eventParams={{ items: [eventItem] }}
url={url || ""}
name={name}
groupName={isVariantOf?.name ?? ""}
brand={brand?.name ?? ""}
productID={productID}
productGroupID={productGroupID}
price={price}
discount={discount}
additionalProperty={additionalProperty}
/>
)}
{platform === "shopify" && (
<AddToCartButtonShopify
eventParams={{ items: [eventItem] }}
url={url || ""}
name={name}
groupName={isVariantOf?.name ?? ""}
brand={brand?.name ?? ""}
productID={productID}
productGroupID={productGroupID}
price={price}
discount={discount}
/>
)}
</>
Expand Down Expand Up @@ -227,7 +188,8 @@ function ProductInfo({ page, layout }: Props) {
</span>
</div>
{/* Analytics Event */}
<SendEventOnLoad
<SendEventOnView
id={id}
event={{
name: "view_item",
params: {
Expand Down
5 changes: 3 additions & 2 deletions components/product/ProductShelf.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SendEventOnLoad } from "$store/components/Analytics.tsx";
import { SendEventOnView } from "$store/components/Analytics.tsx";
import ProductCard, {
Layout as cardLayout,
} from "$store/components/product/ProductCard.tsx";
Expand Down Expand Up @@ -80,7 +80,8 @@ function ProductShelf({
</div>
</>
<SliderJS rootId={id} />
<SendEventOnLoad
<SendEventOnView
id={id}
event={{
name: "view_item_list",
params: {
Expand Down
5 changes: 3 additions & 2 deletions components/product/ProductShelfTabbed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SendEventOnLoad } from "$store/components/Analytics.tsx";
import { SendEventOnView } from "$store/components/Analytics.tsx";
import ProductCard, {
Layout as cardLayout,
} from "$store/components/product/ProductCard.tsx";
Expand Down Expand Up @@ -106,7 +106,8 @@ function TabbedProductShelf({
</div>
</>
<SliderJS rootId={id} />
<SendEventOnLoad
<SendEventOnView
id={id}
event={{
name: "view_item_list",
params: {
Expand Down
13 changes: 8 additions & 5 deletions components/search/SearchResult.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SendEventOnLoad } from "$store/components/Analytics.tsx";
import { SendEventOnView } from "$store/components/Analytics.tsx";
import { Layout as CardLayout } from "$store/components/product/ProductCard.tsx";
import Filters from "$store/components/search/Filters.tsx";
import Icon from "$store/components/ui/Icon.tsx";
import SearchControls from "$store/islands/SearchControls.tsx";
import { useId } from "$store/sdk/useId.ts";
import { useOffer } from "$store/sdk/useOffer.ts";
import type { ProductListingPage } from "apps/commerce/types.ts";
import { mapProductToAnalyticsItem } from "apps/commerce/utils/productToAnalyticsItem.ts";
Expand Down Expand Up @@ -42,6 +43,7 @@ function Result({
const { products, filters, breadcrumb, pageInfo, sortOptions } = page;
const perPage = pageInfo.recordPerPage || products.length;
const offset = pageInfo.currentPage * perPage;
const id = useId();

return (
<>
Expand All @@ -59,7 +61,7 @@ function Result({
<Filters filters={filters} />
</aside>
)}
<div class="flex-grow">
<div class="flex-grow" id={id}>
<ProductGallery
products={products}
offset={offset}
Expand Down Expand Up @@ -92,13 +94,14 @@ function Result({
</div>
</div>
</div>
<SendEventOnLoad
<SendEventOnView
id={id}
event={{
name: "view_item_list",
params: {
// TODO: get category name from search or cms setting
item_list_name: "",
item_list_id: "",
item_list_name: breadcrumb.itemListElement?.at(-1)?.name,
item_list_id: breadcrumb.itemListElement?.at(-1)?.item,
items: page.products?.map((product, index) =>
mapProductToAnalyticsItem({
...(useOffer(product.offers)),
Expand Down
1 change: 1 addition & 0 deletions components/search/Searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ function Searchbar({
product={product}
platform={platform}
index={index}
itemListName="Suggeestions"
/>
</Slider.Item>
))}
Expand Down
Loading

0 comments on commit b289107

Please sign in to comment.