-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix((INT-360): enhancement: shopify ecom fix and enhancement #2493
Conversation
INT-153 Research: Shopify Ecomm spec review
Repo: https://github.com/rudderlabs/rudder-shopify-tracker Analyze whether shopify events are adhering to Rudderstack Ecomm spec Research Spec |
Codecov ReportAll modified lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #2493 +/- ##
===========================================
- Coverage 87.24% 87.10% -0.14%
===========================================
Files 641 613 -28
Lines 28519 28540 +21
Branches 6780 6776 -4
===========================================
- Hits 24880 24861 -19
- Misses 3310 3347 +37
- Partials 329 332 +3
☔ View full report in Codecov by Sentry. |
@@ -3,7 +3,7 @@ const path = require('path'); | |||
const version = 'v0'; | |||
const { RedisDB } = require('./redisConnector'); | |||
jest.mock('ioredis', () => require('../../../test/__mocks__/redis')); | |||
const sourcesList = ['shopify']; | |||
const sourcesList = ['shopify', 'shopify_v2']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets not keep shopify_v2. Lets create a new Shopify dir under v1 dir on the same level as v0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refer this please
const { RedisDB } = require('../../../util/redis/redisConnector'); | ||
const logger = require('../../../logger'); | ||
|
||
const identifierEventLayer = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const identifierEventLayer = { | |
const IdentifierEventLayer = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
src/v0/sources/shopify_v2/config.js
Outdated
statusCode: 200, | ||
}; | ||
|
||
const identifierEvents = ['rudderIdentifier', 'rudderSessionIdentifier']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const identifierEvents = ['rudderIdentifier', 'rudderSessionIdentifier']; | |
const IDENTIFIER_EVENTS = ['rudderIdentifier', 'rudderSessionIdentifier']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
async processIdentifierEvent(event, metricMetadata) { | ||
let value; | ||
let field; | ||
if (event.event === 'rudderIdentifier') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change the argument name to something which provides more clarity event.event
doesn't provide much clarity.
lineItems[element.id] = { | ||
quantity: element?.quantity, | ||
variant_id: element?.variant_id, | ||
key: element?.key, | ||
price: element?.price, | ||
product_id: element?.product_id, | ||
sku: element?.sku, | ||
title: element?.title, | ||
vendor: element?.vendor, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional chaining is not needed here
// eslint-disable-next-line no-param-reassign | ||
event.userId = String(event.userId); | ||
} | ||
if (!get(event, 'traits.email')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!get(event, 'traits.email')) { | |
if (!get(event, 'context.traits.email')) { |
event.setProperty(`integrations.${INTEGRATION}`, true); | ||
event.setProperty('context.library', { | ||
name: 'RudderStack Shopify Cloud', | ||
version: '1.0.0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version: '1.0.0', | |
version: '1.1.0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be a constant this version number based on the implementations appropriate constant should be used
extractCustomFields, | ||
} = require('../../util'); | ||
|
||
const trackLayer = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const trackLayer = { | |
const TrackLayer = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
} | ||
}, | ||
|
||
async processTrackEvent(event, eventName, dbData, metricMetadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async processTrackEvent(event, eventName, dbData, metricMetadata) { | |
async processTrackEvent(shopifyEvent, shopifyEventName, dbData, metricMetadata) { |
return updatedCartProperties; | ||
}, | ||
|
||
async generateProductAddedAndRemovedEvents(event, dbData, metricMetadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async generateProductAddedAndRemovedEvents(event, dbData, metricMetadata) { | |
async generateProductAddedAndRemovedEvents(shopifyEvent, dbData, metricMetadata) { |
// if no prev cart is found we trigger product added event for every line_item present | ||
if (!prevLineItems) { | ||
event?.line_items.forEach((product) => { | ||
const updatedProduct = this.getUpdatedProductProperties(product, event?.id || event?.token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const updatedProduct = this.getUpdatedProductProperties(product, event?.id || event?.token); | |
const updatedProduct = this.getUpdatedProductProperties(product, event.id || event.token); |
const updatedCartProperties = product; | ||
if (updatedQuantity) { | ||
updatedCartProperties.quantity = updatedQuantity; | ||
} | ||
updatedCartProperties.cart_id = cart_token; | ||
return updatedCartProperties; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we calling updatedCartProperties
for this variable we are updating products?
let properties = this.createPropertiesForEcomEvent(event, shopifyTopic); | ||
properties = removeUndefinedAndNullValues(properties); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let properties = this.createPropertiesForEcomEvent(event, shopifyTopic); | |
properties = removeUndefinedAndNullValues(properties); | |
const properties = removeUndefinedAndNullValues(this.createPropertiesForEcomEvent(event, shopifyTopic)); |
); | ||
if (productAddedOrRemovedEvents.length === 0) return [NO_OPERATION_SUCCESS]; | ||
productAddedOrRemovedEvents = productAddedOrRemovedEvents.map((productEvent) => | ||
this.mapCustomerDetails(productEvent, event, dbData, eventName), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.mapCustomerDetails(productEvent, event, dbData, eventName), | |
this.mapCustomerDetails(productEvent, shopifyEvent, dbData, eventName), |
if (!get(payload, 'traits.email')) { | ||
const email = extractEmailFromPayload(event); | ||
if (email) { | ||
updatedPayload.setProperty('traits.email', email); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updatedPayload.setProperty('traits.email', email); | |
updatedPayload.setProperty('context.traits.email', email); |
const cartToken = getCartToken(message, shopifyTopic); | ||
if (!isDefinedAndNotNull(cartToken)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we validate using dbData since we already have that? Why are we validating with cartToken here?
); | ||
if (isDefinedAndNotNull(anonymousId)) { | ||
updatedMessage.setProperty('anonymousId', anonymousId); | ||
} else if (!message.userId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else if (!message.userId) { | |
} else if (!isDefineNotNullandBlank(message.userId)) { |
} else if (!message.userId) { | ||
updatedMessage.setProperty('userId', 'shopify-admin'); | ||
} | ||
if (isDefinedAndNotNull(sessionId)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use not blank as well for empty string
if (SHOPIFY_TO_RUDDER_ECOM_EVENTS_MAP.CART_UPDATED === eventName) { | ||
let productAddedOrRemovedEvents = await this.generateProductAddedAndRemovedEvents( | ||
event, | ||
dbData, | ||
metricMetadata, | ||
); | ||
if (productAddedOrRemovedEvents.length === 0) return [NO_OPERATION_SUCCESS]; | ||
productAddedOrRemovedEvents = productAddedOrRemovedEvents.map((productEvent) => | ||
this.mapCustomerDetails(productEvent, event, dbData, eventName), | ||
); | ||
return productAddedOrRemovedEvents; | ||
} | ||
// if event is checkout updated we get the updated event name | ||
if (SHOPIFY_TO_RUDDER_ECOM_EVENTS_MAP.CHECKOUTS_UPDATE === eventName) { | ||
updatedEventName = this.getUpdatedEventNameForCheckoutUpateEvent(event); | ||
} | ||
if (Object.keys(RUDDER_ECOM_MAP).includes(updatedEventName)) { | ||
payload = this.ecomPayloadBuilder(event, updatedEventName); | ||
} else if (Object.keys(SHOPIFY_NON_ECOM_TRACK_MAP).includes(updatedEventName)) { | ||
payload = this.nonEcomPayloadBuilder(event, updatedEventName); | ||
} else { | ||
stats.increment('invalid_shopify_event', { | ||
event: eventName, | ||
...metricMetadata, | ||
}); | ||
return [NO_OPERATION_SUCCESS]; | ||
} | ||
return [this.mapCustomerDetails(payload, event, dbData, eventName)]; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we try using switch case here?
// return msgpack.encode(lineItems); | ||
}; | ||
|
||
const getUnhashedLineItems = (lineItems) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change fxn name
if (prevQuantity) { | ||
delete prevLineItems[key]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elaborate what are we doing here?
Kudos, SonarCloud Quality Gate passed! |
This PR is considered to be stale. It has been open for 20 days with no further activity thus it is going to be closed in 7 days. To avoid such a case please consider removing the stale label manually or add a comment to the PR. |
Description of the change
We are changing the code base for shopify as there are many layers through which a payload goes to be enhanced
This PR includes the changes regarding the same.
We have used layering concept where we have identifier events Layer, Track event Layer, Identify Events layer and enhancement Layer.
Todo :- Incorporate mapping for each ecommerce event.
Type of change
Related issues
Checklists
Development
Code review