<script src="https://static.runconverge.com/pixels/{YOUR-PUBLIC-TOKEN}" async></script>
<script>
window.cvg||(cvg=function(){cvg.process?cvg.process.apply(cvg,arguments):cvg.queue.push(arguments)},cvg.queue=[]);
cvg({method:"track",eventName:"$page_load"});
</script>
<script>
/**************************************************************************
* Firmhouse Converge Pixel configuration
* storefrontToken: In the firmhouse portal, go to Settings > Integrations > Generate new token > Access type: Storefront
* currency: The currency of your store
*************************************************************************/
const storefrontToken = '{YOUR-STOREFRONT-TOKEN}';
const currency = 'EUR';
/******************************** Globals ********************************/
const aliases = [];
let profileProperties = {};
/* --------------------------------------------------------------------- */
/******************************** Helpers ********************************/
const getCookie = (name) => {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) {
return parts.pop().split(';').shift();
}
return '';
}
const setCookie = (name, value) => {
document.cookie = `${name}=${value}; path=/;`;
}
const isValidEmail = (email) =>
email && /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(email);
const collectProfileProperties = () => {
const $email = document.querySelector('[name="subscription[email]"]')?.value;
const phoneCountry = document.querySelector('#country-listbox li.active')?.getAttribute('data-dial-code');
const phone = document.querySelector('[name="subscription[phone_number]"]')?.value;
const $phone_number = phoneCountry && phone ? `+${phoneCountry} ${phone}` : undefined;
const $first_name = document.querySelector('[name="subscription[name]"]')?.value;
const $last_name = document.querySelector('[name="subscription[last_name]"]')?.value;
const $zip_code = document.querySelector('[name="subscription[zipcode]"]')?.value;
const $city = document.querySelector('[name="subscription[city]"]')?.value;
const $country_code = document.querySelector('[name="subscription[country]"] option:checked')?.value;
profileProperties = {
...profileProperties,
$email,
$phone_number,
$first_name,
$last_name,
$zip_code,
$city,
$country_code,
};
if (isValidEmail($email)) {
aliases.push(`urn:email:${$email}`);
}
}
const getCart = () => fetch(
'https://portal.firmhouse.com/graphql',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Subscription-Token': cartToken,
'X-Project-Access-Token': storefrontToken
},
body: JSON.stringify({
query: `
{
currentCart {
token
orderedProducts {
quantity
product {
title
priceCents
shopifyProductId
shopifyVariantId
sku
}
}
}
}
`,
}),
}
)
.then((response) => response.json())
.then((body) => body.data.currentCart)
.then((cart) => ({
id: cart.token,
currency,
total_price: cart.orderedProducts.reduce((acc, l) => acc + l.product.priceCents * l.quantity, 0) / 100,
items: cart.orderedProducts.map((l) => ({
product_id: l.product.shopifyProductId.split('/').pop(),
variant_id: l.product.shopifyVariantId.split('/').pop(),
sku: l.product.sku,
name: l.product.title,
variant_name: l.product.shopifyVariantId.split('/').pop(),
price: l.product.priceCents / 100,
quantity: l.quantity,
currency
}))
}));
const setupStartedCheckout = (cartPromise, cartToken) => {
if (getCookie('__cvg_started_checkout') !== cartToken) {
cartPromise.then((cart) => {
cvg({method: 'event', event: 'Started Checkout', properties: cart, aliases, profileProperties});
});
setCookie('__cvg_started_checkout', cartToken);
}
}
const setupAddedPaymentInfo = (cartPromise, cartToken) => {
const subscriptionSubmit = document.querySelector('[data-role="subscription-submit"]');
if (subscriptionSubmit) {
subscriptionSubmit.addEventListener('click', () => {
collectProfileProperties();
aliases.push(`urn:email:${profileProperties["$email"]}`);
cartPromise.then((cart) => {
cvg({method: 'event', event: 'Added Payment Info', properties: cart, aliases, profileProperties});
});
});
}
}
/* --------------------------------------------------------------------- */
/******************************** Setup **********************************/
// Get the cart_token from URL or localStorage
const cartToken = (
new URLSearchParams(window.location.search).get('cart_token')
|| localStorage.getItem('Firmhouse.cartToken')
|| getCookie('__cvg_cart_token')
);
// Ensure that no 'dummy' subscription tokens are used for identification (e.g. 'new')
if (cartToken && cartToken.length >= 10) {
aliases.push(`urn:firmhouse:token:${cartToken}`);
setCookie('__cvg_cart_token', cartToken);
} else {
const path = window.location.pathname;
const matches = path.match(/\/subscriptions\/([a-zA-Z0-9]+)/);
const subscriptionToken = matches && matches[1];
if (subscriptionToken && subscriptionToken.length >= 10) {
aliases.push(`urn:firmhouse:token:${subscriptionToken}`);
}
}
/* --------------------------------------------------------------------- */
/******************************** Events **********************************/
cvg({method: 'event', event: '$page_load', aliases, profileProperties});
if (cartToken) {
const cartPromise = getCart();
setupStartedCheckout(cartPromise, cartToken);
setupAddedPaymentInfo(cartPromise, cartToken);
}
/* --------------------------------------------------------------------- */
</script>