Skip to content

Commit

Permalink
feat: adding session Id stitching and upgrading node version to v18 (#30
Browse files Browse the repository at this point in the history
)

* feat: adding sesion Id stitching

* update: sessionId Flow

* taking polltime from env

* chore: update

* fix: remove tls object

* chore: issues resolved

* Version Upgraded to node V18

* chore: variant id introduced

* small fixes
  • Loading branch information
anantjain45823 authored Aug 9, 2023
1 parent 6d6dafc commit dd8bc39
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 57 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18.16.0
165 changes: 109 additions & 56 deletions deviceModeInit.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,26 +130,23 @@ var rudderTracking = (function () {
} else {
console.debug("No heap cookie found.");
}

htmlSelector.buttonAddToCart =
rs$('form[action="/cart/add"] [type="submit"]')
htmlSelector.buttonAddToCart = rs$('form[action="/cart/add"] [type="submit"]')
fetchCart()
.then((cart) => {
const needToUpdateCart = checkCartNeedsToBeUpdated(cart);
if (userLoggedOut || needToUpdateCart) {
updateCartAttribute().then((cart) => {
sendIdentifierToRudderWebhook(cart);
console.debug("Successfully updated cart");
sendIdentifierToRudderWebhook(cart); // sending rudderIdentifier periodically after this
sendSessionIdentifierToRudderWebhook(cart); // sending sessionIdentifier
console.log("Successfully updated cart");
checkAndSendSessionRudderIdentifierPeriodically();
checkAndSendRudderIdentifier(cart, delay = 10000);
}).catch((error) => {
console.debug("Error occurred while updating cart:", error);
});;
}
else {
/* Used else condition as it was otherwise sending rudderIdentifier twice
as previous request didn't get completed
and we tried sending one more
*/
checkAndSendRudderIdentifier();// sending rudderIdentifier periodically after this
});
} else {
checkAndSendSessionRudderIdentifierPeriodically(true);
checkAndSendRudderIdentifier(cart);
}
});
isClientSideIdentifierEventsEnabled().then(response => {
Expand All @@ -167,10 +164,6 @@ var rudderTracking = (function () {

rs$("button[data-search-form-submit]").on("click", trackProductSearch);
}
function checkAndSendRudderIdentifier() {
const timeForCookieUpdate = getTimeForCookieUpdate();
setTimeout(sendRudderIdentifierPeriodically, timeForCookieUpdate);
}
const productIsVisible = (window, element) => {
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
Expand Down Expand Up @@ -254,7 +247,7 @@ var rudderTracking = (function () {
const rudderstackProduct = propertyMapping(
data.product,
productMapping
); // here as well
); // here as well
rudderstackProduct.currency = pageCurrency;
rudderstackProduct.sku = String(
rudderstackProduct.variant[0]?.sku ||
Expand Down Expand Up @@ -343,75 +336,134 @@ var rudderTracking = (function () {
}
}

// TODO: add support for product search

// Shopify Cart Check and Updating of cart attributes
function checkCartNeedsToBeUpdated(cart) {
const { attributes } = cart;
return !(attributes?.rudderAnonymousId);
}
function sendRudderIdentifierPeriodically() {
getAndSendIdentifierToRudderWebhook();
const cookieUpdateFixedInterval = 50 * 60 * 1000; // 50 mins
setInterval(getAndSendIdentifierToRudderWebhook
, cookieUpdateFixedInterval);
}
function getAndSendIdentifierToRudderWebhook() {
fetchCart().then((cart) => {
sendIdentifierToRudderWebhook(cart);
})
}
function updateCartAttribute() {
const anonymousId = rudderanalytics.getAnonymousId();
const sessionId = rudderanalytics.getSessionId();
return rs$.post(
window.Shopify.routes.root + "cart/update.json",
{
attributes: {
rudderAnonymousId: anonymousId,
rudderSessionId: sessionId,
},
},
undefined,
"json"
);
}
function getTimeForCookieUpdate() {
const thresholdTime = 50 * 60 * 1000; // 50 mins
const currentTime = Date.now();
const last_updated_at = Number(cookie_action({

// common function for sending anonymousId and sessionId Identifier
function sendToRudderWebhook(data, type, updateTypeCookieFunction, retryAttempt = 0) {
const webhookUrl =
"https://dataplaneUrl_placeHolder/v1/webhook?writeKey=writeKey_placeHolder";
const timeToRetry = 1000; // 1 second
const maxRetries = 3;
if (maxRetries > retryAttempt) {
rs$
.ajax({
url: webhookUrl,
method: "POST",
contentType: "application/json",
data: JSON.stringify(data),
})
.then(() => {
updateTypeCookieFunction();
console.log(`Successfully sent ${type} event to rudderstack`);
})
.catch(() => {
setTimeout(() => { sendToRudderWebhook(data, type, updateTypeCookieFunction, retryAttempt + 1) }, timeToRetry * (retryAttempt));
});
} else {
console.log(`Failed to sent ${type} event to rudderstack`);
}
}

//functions to send sessionId Identifier
function sendSessionIdentifierToRudderWebhook(cart) {
const data = {
event: "rudderSessionIdentifier",
sessionId: rudderanalytics.getSessionId(),
cartToken: cart.token,
};
const type = "sessionIdentifier";
sendToRudderWebhook(data, type, updateSessionCookie)
}
function checkSessionCookieNeedsToBeUpdated() {
const current_session_id = rudderanalytics.getSessionId();
const prev_rs_session_id = cookie_action({
action: "get",
name: "rs_shopify_cart_identified_at",
}));
const timeToUpdate = thresholdTime - (currentTime - last_updated_at);
return timeToUpdate
name: "rs_shopify_session_id",
});
return current_session_id != prev_rs_session_id
}
function checkAndSendSessionRudderIdentifier() {
const needToUpdateSessionCookie = checkSessionCookieNeedsToBeUpdated();
if (needToUpdateSessionCookie) {
updateCartAttribute().then((cart) => { // updating the sessionId in cart object
sendSessionIdentifierToRudderWebhook(cart); // sending sessionIdentifier
});
}
}
function updateSessionCookie() {
const cookieOptions = {
action: "set",
expire_hr: 1,
name: "rs_shopify_session_id",
value: rudderanalytics.getSessionId(),
}
cookie_action(cookieOptions);
}
function checkAndSendSessionRudderIdentifierPeriodically(checkNow = false) {
const pollTimeToCheckAndSendSessionIdentifier = "sessionIdentifierPollTime_placeHolder";
if (checkNow) {
checkAndSendSessionRudderIdentifier();
}
setInterval(() => { checkAndSendSessionRudderIdentifier() }, pollTimeToCheckAndSendSessionIdentifier)
}

// functions for sending anonymousId Identifier
function checkAndSendRudderIdentifier(cart, delay = 0) {
setTimeout(() => {
const timeForCookieUpdate = getTimeForCookieUpdate();
setTimeout(() => { sendRudderIdentifierPeriodically(cart) }, timeForCookieUpdate);
}, delay)
}
function sendRudderIdentifierPeriodically(cart) {
sendIdentifierToRudderWebhook(cart);
const cookieUpdateFixedInterval = 50 * 60 * 1000; // 50 mins
setInterval(() => { sendIdentifierToRudderWebhook(cart) }
, cookieUpdateFixedInterval);
}
function sendIdentifierToRudderWebhook(cart) {
const webhookUrl =
"https://dataplaneUrl_placeHolder/v1/webhook?writeKey=writeKey_placeHolder";
const data = {
event: "rudderIdentifier",
anonymousId: rudderanalytics.getAnonymousId(),
cartToken: cart.token,
cart: cart
};
rs$
.ajax({
url: webhookUrl,
method: "POST",
contentType: "application/json",
data: JSON.stringify(data),
})
.then(() => {
updateTimeStampForIdentifierEvent();
console.debug("Successfully sent identifier event to rudderstack");
})
.catch(() => {
console.debug("Failed to sent identifier event to rudderstack");
});
sendToRudderWebhook(data, 'anonymousIdentifier', updateTimeStampForIdentifierEvent);
}

function getTimeForCookieUpdate() {
const thresholdTime = 50 * 60 * 1000; // 50 mins
const currentTime = Date.now();
const last_updated_at = Number(cookie_action({
action: "get",
name: "rs_shopify_cart_identified_at",
}));
const timeToUpdate = thresholdTime - (currentTime - last_updated_at);
return timeToUpdate
}

function updateTimeStampForIdentifierEvent() {
const cookieOptions = {
action: "set",
expire_hr: 2,
expire_hr: 1,
name: "rs_shopify_cart_identified_at",
value: `${Date.now()}`
}
Expand All @@ -425,6 +477,7 @@ var rudderTracking = (function () {
"JSON"
);
}

function trackProductSearch() {
const query =
rs$("button[data-search-form-submit]")
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rudderstack-shopify-tracker",
"version": "1.0.0",
"version": "1.1.0",
"description": "Tracks client-side events on Shopify stores",
"main": "main.js",
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions router.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ router.get("/load", async (ctx) => {
d = d.replace("dataPlaneUrl", dataPlaneUrl);
d = d.replace("configBackendUrl", configUrl);

const pollTimeForSessionIdentifierCheck = process.env?.pollTimeForSessionIdentifierCheck || 5 * 60 * 1000; // default 5 mins
deviceModeInit = deviceModeInit.replace(/sessionIdentifierPollTime_placeHolder/g, pollTimeForSessionIdentifierCheck);
deviceModeInit = deviceModeInit.replace(/dataplaneUrl_placeHolder/g, dataPlaneUrl);
deviceModeInit = deviceModeInit.replace(/writeKey_placeHolder/g, writeKey);
deviceModeInit = deviceModeInit.replace(/configUrl_placeholder/g, configUrl);
Expand Down

0 comments on commit dd8bc39

Please sign in to comment.