Skip to content
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

refactor: Create Interfaces for eCommerce #964

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions src/ecommerce.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {
ProductAction,
Product,
Promotion,
CommerceEvent,
} from '@mparticle/event-models';
import {
SDKEventAttrs,
SDKEventOptions,
TransactionAttributes,
} from '@mparticle/web-sdk';
import { valueof } from './utils';
import {
ProductActionType,
PromotionActionType,
CommerceEventType,
EventType,
} from './types';
import {
SDKEvent,
SDKEventCustomFlags,
SDKImpression,
SDKProduct,
SDKProductImpression,
SDKPromotion,
} from './sdkRuntimeModels';

interface IECommerceShared {
createProduct(
name: string,
sku: string | number,
price: string | number,
quantity?: string | number,
variant?: string,
category?: string,
brand?: string,
position?: number,
couponCode?: string,
attributes?: SDKEventAttrs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

,

): SDKProduct | null;
createImpression(name: string, product: Product): SDKImpression | null;
createPromotion(
id: string | number,
creative?: string,
name?: string,
position?: number
): SDKPromotion | null;
createTransactionAttributes(
id: string | number,
affiliation?: string,
couponCode?: string,
revenue?: string | number,
shipping?: string | number,
tax?: number
): TransactionAttributes | null;
expandCommerceEvent(event: CommerceEvent): SDKEvent[] | null;
}

export interface SDKCart {
add(product: SDKProduct | SDKProduct[], logEvent?: boolean): void;
remove(product: SDKProduct | SDKProduct[], logEvent?: boolean): void;
clear(): void;
}

// Used for the public `eCommerce` namespace
export interface SDKECommerceAPI extends IECommerceShared {
logCheckout(
step: number,
option?: string,
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags
): void;
logImpression(
impression: SDKProductImpression,
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags,
eventOptions?: SDKEventOptions
): void;
logProductAction(
productActionType: valueof<typeof ProductActionType>,
product: SDKProduct | SDKProduct[],
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags,
transactionAttributes?: TransactionAttributes,
eventOptions?: SDKEventOptions
): void;
logPromotion(
type: valueof<typeof PromotionActionType>,
promotion: SDKPromotion,
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags,
eventOptions?: SDKEventOptions
): void;
setCurrencyCode(code: string): void;

/*
* @deprecated
*/
Cart: SDKCart;

/*
* @deprecated
*/
logPurchase(
alexs-mparticle marked this conversation as resolved.
Show resolved Hide resolved
transactionAttributes: TransactionAttributes,
product: SDKProduct | SDKProduct[],
clearCart?: boolean,
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags
): void;

/*
* @deprecated
*/
logRefund(
alexs-mparticle marked this conversation as resolved.
Show resolved Hide resolved
transactionAttributes: TransactionAttributes,
product: SDKProduct | SDKProduct[],
clearCart?: boolean,
attrs?: SDKEventAttrs,
customFlags?: SDKEventCustomFlags
): void;
}

interface ExtractedActionAttributes {
Affiliation?: string;
'Coupon Code'?: string;
'Total Amount'?: number;
'Shipping Amount'?: number;
'Tax Amount'?: number;
'Checkout Option'?: string;
'Checkout Step'?: number;
'Transaction ID'?: string;
}
interface ExtractedProductAttributes {
'Coupon Code'?: string;
Brand?: string;
Category?: string;
Name?: string;
Id?: string;
'Item Price'?: number;
Quantity?: number;
Position?: number;
Variant?: string;
'Total Product Amount': number;
}
interface ExtractedPromotionAttributes {
Id?: string;
Creative?: string;
Name?: string;
Position?: number;
}
interface ExtractedTransactionId {
'Transaction ID'?: string;
}

// Used for the private `_Ecommerce` namespace
export interface IECommerce extends IECommerceShared {
buildProductList(event: SDKEvent, product: Product | Product[]): Product[];
convertProductActionToEventType(
productActionType: valueof<typeof ProductActionType>
): // https://go.mparticle.com/work/SQDSDKS-4801
typeof CommerceEventType | typeof EventType | null;
convertPromotionActionToEventType(
promotionActionType: valueof<typeof PromotionActionType>
): typeof CommerceEventType | null;
convertTransactionAttributesToProductAction(
transactionAttributes: TransactionAttributes,
productAction: ProductAction
): void;
alexs-mparticle marked this conversation as resolved.
Show resolved Hide resolved
createCommerceEventObject(
customFlags: SDKEventCustomFlags,
options?: SDKEventOptions
): SDKEvent | null;
expandProductAction(commerceEvent: CommerceEvent): SDKEvent[];
expandProductImpression(commerceEvent: CommerceEvent): SDKEvent[];
expandPromotionAction(commerceEvent: CommerceEvent): SDKEvent[];
extractActionAttributes(
attributes: ExtractedActionAttributes,
productAction: ProductAction
): void;
extractProductAttributes(
attributes: ExtractedProductAttributes,
product: Product
): void;
extractPromotionAttributes(
attributes: ExtractedPromotionAttributes,
promotion: Promotion
): void;
extractTransactionId(
attributes: ExtractedTransactionId,
productAction: ProductAction
): void;
generateExpandedEcommerceName(eventName: string, plusOne: boolean): string;
getProductActionEventName(
productActionType: valueof<typeof ProductActionType>
): string;
getPromotionActionEventName(
promotionActionType: valueof<typeof PromotionActionType>
): string;
sanitizeAmount(amount: string | number, category: string): number;
}
9 changes: 9 additions & 0 deletions src/ecommerce.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ var Messages = Constants.Messages;

export default function Ecommerce(mpInstance) {
var self = this;

// https://go.mparticle.com/work/SQDSDKS-4801
this.convertTransactionAttributesToProductAction = function(
transactionAttributes,
productAction
Expand Down Expand Up @@ -103,8 +105,11 @@ export default function Ecommerce(mpInstance) {
return Types.CommerceEventType.ProductRemoveFromCart;
case Types.ProductActionType.RemoveFromWishlist:
return Types.CommerceEventType.ProductRemoveFromWishlist;

// https://go.mparticle.com/work/SQDSDKS-4801
case Types.ProductActionType.Unknown:
return Types.EventType.Unknown;

alexs-mparticle marked this conversation as resolved.
Show resolved Hide resolved
case Types.ProductActionType.ViewDetail:
return Types.CommerceEventType.ProductViewDetail;
default:
Expand Down Expand Up @@ -139,6 +144,7 @@ export default function Ecommerce(mpInstance) {
);
};

// https://go.mparticle.com/work/SQDSDKS-4801
this.extractProductAttributes = function(attributes, product) {
if (product.CouponCode) {
attributes['Coupon Code'] = product.CouponCode;
Expand Down Expand Up @@ -170,12 +176,14 @@ export default function Ecommerce(mpInstance) {
attributes['Total Product Amount'] = product.TotalAmount || 0;
};

// https://go.mparticle.com/work/SQDSDKS-4801
this.extractTransactionId = function(attributes, productAction) {
if (productAction.TransactionId) {
attributes['Transaction Id'] = productAction.TransactionId;
}
};

// https://go.mparticle.com/work/SQDSDKS-4801
this.extractActionAttributes = function(attributes, productAction) {
self.extractTransactionId(attributes, productAction);

Expand Down Expand Up @@ -208,6 +216,7 @@ export default function Ecommerce(mpInstance) {
}
};

// https://go.mparticle.com/work/SQDSDKS-4801
this.extractPromotionAttributes = function(attributes, promotion) {
if (promotion.Id) {
attributes['Id'] = promotion.Id;
Expand Down
12 changes: 6 additions & 6 deletions src/identity-user-interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import { AllUserAttributes, MPID, Product, User } from '@mparticle/web-sdk';
import { SDKIdentityTypeEnum } from './identity.interfaces';
import { MessageType } from './types';
import { BaseEvent } from './sdkRuntimeModels';
import { BaseEvent, SDKProduct } from './sdkRuntimeModels';
import Constants from './constants';
const { HTTPCodes } = Constants;

// Cart is Deprecated and private to mParticle user in @mparticle/web-sdk
// but we need to expose it here for type safety in some of our tests
interface Cart {
interface ICart {
/**
* @deprecated Cart persistence in mParticle has been deprecated. Please use mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, [products])
*/
add: (product: Product, logEventBoolean?: boolean) => void;
add: (product: SDKProduct, logEventBoolean?: boolean) => void;
/**
* @deprecated Cart persistence in mParticle has been deprecated. Please use mParticle.eCommerce.logProductAction(mParticle.ProductActionType.RemoveFromCart, [products])
*/
remove: (product: Product, logEventBoolean?: boolean) => void;
remove: (product: SDKProduct, logEventBoolean?: boolean) => void;
/**
* @deprecated Cart persistence in mParticle has been deprecated.
*/
clear: () => void;
/**
* @deprecated Cart Products have been deprecated
*/
getCartProducts: () => Product[];
getCartProducts: () => SDKProduct[];
}

// https://go.mparticle.com/work/SQDSDKS-5033
Expand All @@ -36,7 +36,7 @@ export interface IMParticleUser extends User {
/*
* @deprecated
*/
getCart(): Cart;
getCart(): ICart;
}

export interface ISDKUserIdentity {
Expand Down
13 changes: 11 additions & 2 deletions src/sdkRuntimeModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import IntegrationCapture from './integrationCapture';
import { INativeSdkHelpers } from './nativeSdkHelpers.interfaces';
import { ICookieSyncManager, IPixelConfiguration } from './cookieSyncManager';
import { IEvents } from './events.interfaces';
import { IECommerce, SDKECommerceAPI } from './ecommerce.interfaces';

// TODO: Resolve this with version in @mparticle/web-sdk
export type SDKEventCustomFlags = Dictionary<any>;
Expand Down Expand Up @@ -107,6 +108,11 @@ export interface SDKPromotion {
Position?: string;
}

export interface SDKImpression {
Name: string;
Product: SDKProduct;
}

export interface SDKProductImpression {
ProductImpressionList?: string;
ProductList?: SDKProduct[];
Expand Down Expand Up @@ -150,7 +156,9 @@ export interface SDKProduct {
Position?: number;
CouponCode?: string;
TotalAmount?: number;
Attributes?: { [key: string]: string };

// https://go.mparticle.com/work/SQDSDKS-4801
Attributes?: Record<string, unknown> | null;
}

export interface MParticleWebSDK {
Expand All @@ -170,6 +178,7 @@ export interface MParticleWebSDK {
_Forwarders: any;
_Helpers: SDKHelpersApi;
_Events: IEvents;
_Ecommerce: IECommerce;
config: SDKInitConfig;
_ServerModel: IServerModel;
_SessionManager: ISessionManager;
Expand Down Expand Up @@ -208,7 +217,7 @@ export interface MParticleWebSDK {
eventOptions?: SDKEventOptions
): void;
logBaseEvent(event: BaseEvent, eventOptions?: SDKEventOptions): void;
eCommerce: any;
eCommerce: SDKECommerceAPI;
logLevel: string;
ProductActionType: SDKProductActionType;
generateHash(value: string): string;
Expand Down
2 changes: 1 addition & 1 deletion src/sdkToEventsApiConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export function convertProducts(
price: sdkProduct.Price,
quantity: sdkProduct.Quantity,
coupon_code: sdkProduct.CouponCode,
custom_attributes: sdkProduct.Attributes,
custom_attributes: sdkProduct.Attributes as Record<string, string>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see if this should be string, unknown

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Record<string, string> doesn't work because EventsApi.Product requires custom_attributes to be [key: string]: string

};
products.push(product);
}
Expand Down
2 changes: 1 addition & 1 deletion src/serverModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export interface IProductV2DTO {
ps: number;
cc: string | number;
tpa: number;
attrs: Record<string, string> | null;
attrs: Record<string, unknown> | undefined;
}

export interface IPromotionV2DTO {
Expand Down
10 changes: 2 additions & 8 deletions test/src/tests-batchUploader_3.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import sinon from 'sinon';
import { urls, apiKey, MPConfig, testMPID } from './config/constants';
import {
BaseEvent,
MParticleWebSDK,
SDKEvent,
SDKProductActionType,
} from '../../src/sdkRuntimeModels';
import { Batch, CustomEventData } from '@mparticle/event-models';
import Utils from './config/utils';
import { BatchUploader } from '../../src/batchUploader';
import { expect } from 'chai';
import _BatchValidator from '../../src/mockBatchCreator';
import Logger from '../../src/logger.js';
import { event0, event1, event2, event3 } from '../fixtures/events';
import fetchMock from 'fetch-mock/esm/client';
import { ProductActionType } from '../../src/types';
const { fetchMockSuccess, waitForCondition, hasIdentifyReturned } = Utils;

declare global {
Expand Down Expand Up @@ -137,7 +131,7 @@ describe('batch uploader', () => {
window.mParticle.logEvent('Test Event');

var product1 = window.mParticle.eCommerce.createProduct('iphone', 'iphoneSKU', 999);
window.mParticle.eCommerce.logProductAction(SDKProductActionType.AddToCart, product1);
window.mParticle.eCommerce.logProductAction(ProductActionType.AddToCart, product1);

const lastCall = fetchMock.lastCall();
const endpoint = lastCall[0];
Expand Down
Loading
Loading