Skip to content

Commit

Permalink
Merge branch 'develop' into feature/PM-563-dl-add-to-cart-step2
Browse files Browse the repository at this point in the history
  • Loading branch information
hero-dokane committed Oct 28, 2024
2 parents 95537b0 + b9f0286 commit 84f8d9b
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 67 deletions.
103 changes: 58 additions & 45 deletions blocks/plans-quote/form.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { jsx } from '../../scripts/scripts.js';
import { isCanada } from '../../scripts/lib-franklin.js';
import Loader from './loader.js';
import APIClient from '../../scripts/24petwatch-api.js';
import APIClient, { getAPIBaseUrl } from '../../scripts/24petwatch-api.js';
import {
COOKIE_NAME_SAVED_OWNER_ID,
SS_KEY_FORM_ENTRY_URL,
Expand All @@ -19,6 +19,7 @@ import {
isSummaryPage,
getSelectedProductAdditionalInfo,
getItemInfoFragment,
DL_EVENTS,
} from '../../scripts/24petwatch-utils.js';
import { getConfigValue } from '../../scripts/configs.js';
import { trackGTMEvent } from '../../scripts/lib-analytics.js';
Expand All @@ -39,7 +40,26 @@ const usedChipNumbers = new Set();

const promoResultKey = await getConfigValue('promo-result');

export default function formDecoration(block, apiBaseUrl) {
const apiBaseUrl = await getAPIBaseUrl();
const APIClientObj = new APIClient(apiBaseUrl);

// eslint-disable-next-line no-shadow
async function getPurchaseSummary(ownerId) {
Loader.showLoader();
// eslint-disable-next-line no-shadow
let purchaseSummary = {};
try {
purchaseSummary = await APIClientObj.getPurchaseSummary(ownerId);
} catch (status) {
// eslint-disable-next-line no-console
console.log('Failed to get the purchase summary for owner:', ownerId, ' status:', status);
}
Loader.hideLoader();

return purchaseSummary;
}

export default function formDecoration(block) {
// prepare for Canada vs US
const currencyValue = isCanada ? CURRENCY_CANADA : CURRENCY_US;
const zipcodeLabel = isCanada ? 'Postal code*' : 'Zip code*';
Expand Down Expand Up @@ -181,7 +201,6 @@ export default function formDecoration(block, apiBaseUrl) {

Loader.addLoader();

const APIClientObj = new APIClient(apiBaseUrl);
const countryId = isCanada ? 1 : 2;
const formData = {};
const breedLists = {};
Expand Down Expand Up @@ -649,58 +668,48 @@ export default function formDecoration(block, apiBaseUrl) {
}
}

function instrumentTracking(productName) {
const currentPath = window.location.pathname;
const { microchip = '' } = formData || {};

let productType = productName || null;

if (!productType) {
if (currentPath.includes(PET_PLANS_LPM_URL)) {
productType = 'Lifetime Protection Membership';
} else if (currentPath.includes(PET_PLANS_LPM_PLUS_URL)) {
productType = 'Lifetime Protection Membership - PLUS';
} else if (currentPath.includes(PET_PLANS_ANNUAL_URL)) {
productType = 'Annual Protection Membership';
}
}

if (!productType) {
console.error('Product type could not be determined.');
return;
}

// call instrument tracking
const trackingData = {
ecommerce: {
// New GTM dataLayer
product_type: productType, // annual protection membership
items: [
{
item_name: productType,
// coupon: formData.promoCode,
function setDataLayer(data) {
const dlItems = [];

if ('petSummaries' in data) {
const { petSummaries } = data;
let membershipName = '';
if (petSummaries && petSummaries.length > 0) {
petSummaries.forEach((pet) => {
membershipName = pet.membershipName ?? '';
// push each item object to items array
dlItems.push({
item_name: membershipName,
currency: currencyValue,
discount: '', // not available until step 2
discount: pet.nonInsurancePetSummary?.discount ?? '',
item_category: 'membership',
item_variant: '', // okay to be left empty
microchip_number: microchip,
product_type: productType,
price: '', // not available until step 2
quantity: 1,
microchip_number: pet.microChipNumber ?? '',
product_type: membershipName,
price: pet.nonInsurancePetSummary?.amount ?? '',
quantity: pet.nonInsurancePetSummary?.membership?.quantity ?? '1',
});
});

const trackingData = {
ecommerce: {
product_type: membershipName,
items: dlItems,
},
],
},
};
};

// send the GTM event
trackGTMEvent('add_to_cart', trackingData);
// send the GTM event
trackGTMEvent(DL_EVENTS.add, trackingData);
}
}
}

async function executeSubmit() {
Loader.showLoader();

const ownerId = (!formData.ownerId) ? '' : formData.ownerId;
await saveOwner(ownerId); // Create or Update the owner

if (!formData.ownerId) {
// eslint-disable-next-line no-console
console.log('Failed to save the owner.');
Expand Down Expand Up @@ -739,8 +748,10 @@ export default function formDecoration(block, apiBaseUrl) {
return;
}

const getPurchaseSummaryDetails = await getPurchaseSummary(formData.ownerId);

// call instrument tracking
instrumentTracking();
setDataLayer(getPurchaseSummaryDetails);

Loader.hideLoader();

Expand All @@ -760,8 +771,10 @@ export default function formDecoration(block, apiBaseUrl) {
return;
}

const getPurchaseSummaryDetails = await getPurchaseSummary(formData.ownerId);

// call instrument tracking
instrumentTracking(productName);
setDataLayer(getPurchaseSummaryDetails);

Loader.hideLoader();
window.location.reload();
Expand Down
167 changes: 145 additions & 22 deletions blocks/plans-quote/summary-quote.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
getCookie,
getSelectedProductAdditionalInfo,
getItemInfoFragment,
CURRENCY_CANADA,
CURRENCY_US,
SS_KEY_SUMMARY_ACTION,
DL_EVENTS,
} from '../../scripts/24petwatch-utils.js';
import { isCanada } from '../../scripts/lib-franklin.js';
import { trackGTMEvent } from '../../scripts/lib-analytics.js';
import { getConfigValue } from '../../scripts/configs.js';

export default async function decorateSummaryQuote(block, apiBaseUrl) {
Expand Down Expand Up @@ -42,6 +48,96 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {
return purchaseSummary;
}

async function getPet(petId) {
try {
const data = await APIClientObj.getPet(petId);
return data;
} catch (status) {
// eslint-disable-next-line no-console
console.log('Failed to get the pet', ' status:', status);
return [];
}
}

function setDataLayer(data, event, petData = '') {
const currencyValue = isCanada ? CURRENCY_CANADA : CURRENCY_US;
const dlItems = [];
// set items array
if ('petSummaries' in data) {
const { petSummaries } = data;
if (petSummaries && petSummaries.length > 0) {
petSummaries.forEach((pet) => {
// push each item object to items array
dlItems.push({
item_name: pet.membershipName ?? '',
currency: currencyValue,
discount: pet.nonInsurancePetSummary?.discount ?? '',
item_category: 'membership', // membership
item_variant: '', // okay to be left empty
price: pet.nonInsurancePetSummary?.amount ?? '',
quantity: pet.nonInsurancePetSummary?.membership?.quantity ?? '1',
microchip_number: pet.microChipNumber ?? '',
product_type: pet.membershipName ?? '',
});
});
}
}
// cart view
if (event === DL_EVENTS.view) {
const viewCartDL = {
ecommerce: {
value: purchaseSummary?.summary?.totalDueToday,
currency: currencyValue,
items: dlItems,
},
};
// Add view cart event
trackGTMEvent(DL_EVENTS.view, viewCartDL);
}
// remove from cart
if (event === DL_EVENTS.remove) {
// check we have all required data
if ('petSummaries' in data && 'microchipId' in petData) {
const { petSummaries } = data;
const microchip = petData.microchipId;
const petIndex = petSummaries.findIndex((item) => item.microChipNumber === microchip);
const petSummary = petSummaries[petIndex];
if (petSummary) {
// remove cart DL object
const removeCartDL = {
ecommerce: {
items: [{
item_name: petSummary.membershipName ?? '',
currency: currencyValue,
discount: petSummary.nonInsurancePetSummary?.discount ?? '',
item_category: 'membership', // membership
item_variant: '', // okay to be left empty
price: petSummary.nonInsurancePetSummary?.amount ?? '',
quantity: 1,
microchip_number: microchip ?? '',
product_type: petSummary.membershipName ?? '',
}],
},
};
// Add view cart event
trackGTMEvent(DL_EVENTS.remove, removeCartDL);
}
}
}
// begin checkout
if (event === DL_EVENTS.checkout) {
const checkoutCartDL = {
ecommerce: {
value: purchaseSummary?.summary?.totalDueToday,
currency: currencyValue,
items: dlItems,
},
};
// Add checkout cart event
trackGTMEvent(DL_EVENTS.checkout, checkoutCartDL);
}
}

Loader.showLoader();
try {
ownerData = await APIClientObj.getOwner(ownerId);
Expand Down Expand Up @@ -102,31 +198,33 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {
console.error('Invalid entry URL');
}

const payload = {
payload: {
Data: {
if (selectedProducts.length > 0 && petsList.length > 0) {
const payload = {
payload: {
Data: {
ContactKey: ownerData.email,
EmailAddress: ownerData.email,
OrderCompleted: false,
OwnerId: ownerData.id,
PetId: selectedProducts[0].petID,
PetName: petsList[0].petName,
SiteURL: entryURL,
Species: petsList[0].speciesId === 1 ? 'Dog' : 'Cat',
},
EventDefinitionKey: 'APIEvent-6723a35b-b066-640c-1d7b-222f98caa9e1',
ContactKey: ownerData.email,
EmailAddress: ownerData.email,
OrderCompleted: false,
OwnerId: ownerData.id,
PetId: selectedProducts[0].petID,
PetName: petsList[0].petName,
SiteURL: entryURL,
Species: petsList[0].speciesId === 1 ? 'Dog' : 'Cat',
},
EventDefinitionKey: 'APIEvent-6723a35b-b066-640c-1d7b-222f98caa9e1',
ContactKey: ownerData.email,
},
};
};

const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
};
await fetch(salesforceProxyEndpoint, options);
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
};
await fetch(salesforceProxyEndpoint, options);
}

Loader.hideLoader();
}
Expand All @@ -149,12 +247,19 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {

async function removePet(petId) {
Loader.showLoader();
// capture pet info before delete
const petInfo = await getPet(petId);
try {
await APIClientObj.deletePet(petId);
} catch (status) {
// eslint-disable-next-line no-console
console.log('Failed to delete the pet:', petId, ' status:', status);
}
// set dataLayer
if (purchaseSummary && petInfo) {
sessionStorage.setItem(SS_KEY_SUMMARY_ACTION, DL_EVENTS.remove);
setDataLayer(purchaseSummary, DL_EVENTS.remove, petInfo);
}
Loader.hideLoader();
window.location.reload();
}
Expand Down Expand Up @@ -281,6 +386,17 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {
const confirmationDialogYes = document.getElementById('confirmation-dialog-yes');
const confirmationDialogNo = document.getElementById('confirmation-dialog-no');

// Trigger cart view DL event
if (purchaseSummary) {
// to avoid page view DL events on page refresh after add and remove
// const lastFormAction = sessionStorage.getItem(SS_KEY_SUMMARY_ACTION);
// if (!lastFormAction || (lastFormAction && !lastFormAction.includes(DL_EVENTS.remove))) {
// setDataLayer(purchaseSummary, DL_EVENTS.view);
// }
// leave default cart view on any page refresh
setDataLayer(purchaseSummary, DL_EVENTS.view);
}

function editPetHandler(petID) {
confirmationDialogHeader.textContent = 'Edit Confirmation';
confirmationDialogNote.textContent = 'Please note: If you edit the information, the system will return you to the beginning of the order process.';
Expand Down Expand Up @@ -361,6 +477,11 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {
try {
const data = await APIClientObj.postSalesForPayment(ownerData.id, ownerData.cartFlow);
if (data.isSuccess) {
// trigger DL event
if (purchaseSummary) {
sessionStorage.removeItem(SS_KEY_SUMMARY_ACTION);
setDataLayer(purchaseSummary, DL_EVENTS.checkout);
}
window.location.href = replaceUrlPlaceholders(
data.paymentProcessorRedirectBackURL,
data.paymentProcessingUserId,
Expand All @@ -380,6 +501,8 @@ export default async function decorateSummaryQuote(block, apiBaseUrl) {
addPetButton.onclick = () => {
if (formWrapper.innerHTML === '') {
formDecoration(formWrapper, apiBaseUrl);
// set sessionStorage with add action
sessionStorage.setItem(SS_KEY_SUMMARY_ACTION, DL_EVENTS.add);
} else {
formWrapper.innerHTML = '';
}
Expand Down
Loading

0 comments on commit 84f8d9b

Please sign in to comment.