Skip to content

Commit

Permalink
Add storefront events to recommendations block
Browse files Browse the repository at this point in the history
  • Loading branch information
herzog31 committed Mar 7, 2024
1 parent ac5c938 commit d0554f4
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 3 deletions.
60 changes: 57 additions & 3 deletions blocks/product-recommendations/product-recommendations.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
import { performCatalogServiceQuery } from '../../scripts/commerce.js';

const recommendationsQuery = `query GetRecommendations(
Expand All @@ -24,6 +25,8 @@ const recommendationsQuery = `query GetRecommendations(
images {
url
}
externalId
__typename
}
storefrontLabel
totalProducts
Expand All @@ -50,11 +53,17 @@ function renderPlaceholder(block) {
</div>`;
}

function renderItem(product) {
function renderItem(unitId, product) {
const urlKey = product.url.split('/').pop().replace('.html', '');
const image = product.images[0]?.url;

return document.createRange().createContextualFragment(`<div class="product-grid-item">
const clickHandler = () => {
window.adobeDataLayer.push((dl) => {
dl.push({ event: 'recs-item-click', eventInfo: { ...dl.getState(), unitId, productId: parseInt(product.externalId, 10) || 0 } });
});
};

const item = document.createRange().createContextualFragment(`<div class="product-grid-item">
<a href="/products/${urlKey}/${product.sku.toLowerCase()}">
<picture>
<source type="image/webp" srcset="${image}?width=300&format=webply&optimize=medium" />
Expand All @@ -63,6 +72,9 @@ function renderItem(product) {
<span>${product.name}</span>
</a>
</div>`);
item.querySelector('a').addEventListener('click', clickHandler);

return item;
}

function renderItems(block, recommendations) {
Expand All @@ -74,6 +86,10 @@ function renderItems(block, recommendations) {
return;
}

window.adobeDataLayer.push((dl) => {
dl.push({ event: 'recs-unit-impression-render', eventInfo: { ...dl.getState(), unitId: recommendation.unitId } });
});

// Title
block.querySelector('h2').textContent = recommendation.storefrontLabel;

Expand All @@ -82,10 +98,38 @@ function renderItems(block, recommendations) {
grid.innerHTML = '';
const { productsView } = recommendation;
productsView.forEach((product) => {
grid.appendChild(renderItem(product));
grid.appendChild(renderItem(recommendation.unitId, product));
});

const inViewObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
window.adobeDataLayer.push((dl) => {
dl.push({ event: 'recs-unit-view', eventInfo: { ...dl.getState(), unitId: recommendation.unitId } });
});
inViewObserver.disconnect();
}
});
});
inViewObserver.observe(block);
}

const mapUnit = (unit) => ({
...unit,
unitType: 'primary',
searchTime: 0,
primaryProducts: unit.totalProducts,
backupProducts: 0,
products: unit.productsView.map((product, index) => ({
...product,
rank: index,
score: 0,
productId: parseInt(product.externalId, 10) || 0,
type: '?',
queryType: product.__typename,
})),
});

async function loadRecommendation(block, context) {
// Only proceed if all required data is available
if (!context.pageType
Expand All @@ -108,8 +152,18 @@ async function loadRecommendation(block, context) {
console.error('Error parsing product view history', e);

Check warning on line 152 in blocks/product-recommendations/product-recommendations.js

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
}

window.adobeDataLayer.push((dl) => {
dl.push({ event: 'recs-api-request-sent', eventInfo: { ...dl.getState() } });
});

recommendationsPromise = performCatalogServiceQuery(recommendationsQuery, context);
const { recommendations } = await recommendationsPromise;

window.adobeDataLayer.push((dl) => {
dl.push({ recommendationsContext: { units: recommendations.results.map(mapUnit) } });
dl.push({ event: 'recs-api-response-received', eventInfo: { ...dl.getState() } });
});

renderItems(block, recommendations);
}

Expand Down
241 changes: 241 additions & 0 deletions scripts/acdl/schemas/recommendationsContext.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
{
"type": "object",
"properties": {
"units": {
"type": "array",
"items": {
"$ref": "#/definitions/RecommendationUnit"
}
}
},
"definitions": {
"RecommendationUnit": {
"type": "object",
"properties": {
"unitId": {
"type": "string"
},
"unitName": {
"type": "string"
},
"unitType": {
"type": "string"
},
"searchTime": {
"type": "number"
},
"totalProducts": {
"type": "number"
},
"primaryProducts": {
"type": "number"
},
"backupProducts": {
"type": "number"
},
"products": {
"type": "array",
"items": {
"$ref": "#/definitions/RecommendedProduct"
}
},
"pagePlacement": {
"type": [
"string",
"null"
]
},
"typeId": {
"type": "string"
},
"yOffsetTop": {
"type": [
"number",
"null"
]
},
"yOffsetBottom": {
"type": [
"number",
"null"
]
}
},
"required": [
"unitId",
"unitName",
"unitType",
"searchTime",
"totalProducts",
"primaryProducts",
"backupProducts",
"products",
"pagePlacement",
"typeId"
]
},
"RecommendedProduct": {
"type": "object",
"properties": {
"rank": {
"type": "number"
},
"score": {
"type": "number"
},
"sku": {
"type": "string"
},
"name": {
"type": "string"
},
"productId": {
"type": "number"
},
"shortDescription": {
"type": [
"string",
"null"
]
},
"type": {
"type": "string"
},
"visibility": {
"type": "string"
},
"categories": {
"type": "array",
"items": {
"type": "string"
}
},
"weight": {
"type": "number"
},
"weightType": {
"type": [
"string",
"null"
]
},
"currency": {
"type": "string"
},
"image": {
"$ref": "#/definitions/Image"
},
"smallImage": {
"$ref": "#/definitions/Image"
},
"thumbnailImage": {
"$ref": "#/definitions/Image"
},
"swatchImage": {
"type": [
"string",
"null"
]
},
"url": {
"type": "string"
},
"prices": {
"$ref": "#/definitions/Prices"
},
"queryType": {
"type": "string"
}
},
"required": [
"rank",
"score",
"sku",
"name",
"productId",
"type",
"visibility",
"categories",
"weight",
"url",
"queryType"
]
},
"Image": {
"type": "object",
"properties": {
"label": {
"type": [
"string",
"null"
]
},
"url": {
"type": "string"
}
},
"required": [
"url"
]
},
"Prices": {
"type": "object",
"properties": {
"maximum": {
"$ref": "#/definitions/Price"
},
"minimum": {
"$ref": "#/definitions/Price"
}
},
"required": [
"maximum",
"minimum"
]
},
"Price": {
"type": "object",
"properties": {
"finalAdjustments": {
"type": "array",
"items": {
"$ref": "#/definitions/Adjustment"
}
},
"final": {
"type": "number"
},
"regular": {
"type": "number"
},
"regularAdjustments": {
"type": "array",
"items": {
"$ref": "#/definitions/Adjustment"
}
}
},
"required": [
"finalAdjustments",
"final",
"regular",
"regularAdjustments"
]
},
"Adjustment": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"amount": {
"type": "number"
}
},
"required": [
"code",
"amount"
]
}
}
}
12 changes: 12 additions & 0 deletions scripts/acdl/schemas/recs-api-request-sent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"type": "object",
"properties": {
"event": {
"type": "string",
"const": "recs-api-request-sent"
}
},
"required": [
"event"
]
}
12 changes: 12 additions & 0 deletions scripts/acdl/schemas/recs-api-response-received.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"type": "object",
"properties": {
"event": {
"type": "string",
"const": "recs-api-response-received"
}
},
"required": [
"event"
]
}
Loading

0 comments on commit d0554f4

Please sign in to comment.