-
Notifications
You must be signed in to change notification settings - Fork 30
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
Set user #52
Set user #52
Changes from all commits
29e2d51
cfc93a5
ea35142
4cc5854
55a85ba
e626b22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* @flow */ | ||
|
||
import type { MuseGlobalType } from './types'; | ||
import type { MuseGlobalType } from './lib/types'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it make sense to create a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, but I'd prefer to do that + additional refactoring in another PR if possible. |
||
|
||
declare var __muse__ : MuseGlobalType; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
/* @flow */ | ||
import { getCookie } from './cookie-utils'; | ||
import constants from './constants'; | ||
|
||
const { | ||
storage, | ||
sevenDays | ||
} = constants; | ||
// $FlowFixMe | ||
export const removeFromCart = (items, currentItems = []) => { | ||
return items.reduce((accumulator, item) => { | ||
|
@@ -26,3 +33,39 @@ export const removeFromCart = (items, currentItems = []) => { | |
export const addToCart = (items, currentItems = []) => { | ||
return [ ...currentItems, ...items ]; | ||
}; | ||
// $FlowFixMe | ||
export const composeCart = (type, data) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method now uses 'constants' imported above. Otherwise unchanged. |
||
// Copy the data so we don't modify it outside the scope of this method. | ||
let _data = { ...data }; | ||
|
||
// Devnote: Checking for cookie for backwards compatibility (the cookie check can be removed | ||
// a couple weeks after deploy because any cart cookie storage will be moved to localStorage | ||
// in this function). | ||
const storedCart = window.localStorage.getItem(storage.paypalCrCart) || getCookie(storage.paypalCrCart) || '{}'; | ||
const expiry = window.localStorage.getItem(storage.paypalCrCartExpiry); | ||
const cart = JSON.parse(storedCart); | ||
const currentItems = cart ? cart.items : []; | ||
|
||
if (!expiry) { | ||
window.localStorage.setItem(storage.paypalCrCartExpiry, Date.now() + sevenDays); | ||
} | ||
|
||
switch (type) { | ||
case 'add': | ||
_data.items = addToCart(data.items, currentItems); | ||
break; | ||
case 'set': | ||
_data.items = data.items; | ||
break; | ||
case 'remove': | ||
_data = { ...cart, ...data }; | ||
_data.items = removeFromCart(data.items, currentItems); | ||
break; | ||
default: | ||
throw new Error('invalid cart action'); | ||
} | ||
|
||
window.localStorage.setItem(storage.paypalCrCart, JSON.stringify(_data)); | ||
|
||
return _data; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* @flow */ | ||
export default { | ||
'sevenDays': 6.048e+8, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally, (nitpick) I think its easier to understand if you wrote it like this: 😆 |
||
'accessTokenUrl': 'https://www.paypal.com/muse/api/partner-token', | ||
'storage': { | ||
'paypalCrCart': 'paypal-cr-cart', | ||
'paypalCrCartExpiry': 'paypal-cr-cart-expiry' | ||
}, | ||
'defaultTrackerConfig': { | ||
'user': { | ||
'id': null, | ||
'email': null, | ||
'name': null | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
/* @flow */ | ||
import generate from './generate-id'; | ||
|
||
export const getCookie = (cookieName : string) : string => { | ||
const name = `${ cookieName }=`; | ||
|
@@ -21,3 +22,12 @@ export const setCookie = (cookieName : string, cookieValue : string, expirationM | |
const expires = `expires=${ d.toUTCString() }`; | ||
document.cookie = `${ cookieName }=${ cookieValue }; Path=/; ${ expires }`; | ||
}; | ||
|
||
export const getUserIdCookie = () : ?string => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These methods were removed from 'tracker-component'. They have not been altered. (note: ONE_MONTH_IN_MILLISECONDS should probably be in constants) |
||
return getCookie('paypal-user-id') || null; | ||
}; | ||
|
||
export const setRandomUserIdCookie = () : void => { | ||
const ONE_MONTH_IN_MILLISECONDS = 30 * 24 * 60 * 60 * 1000; | ||
setCookie('paypal-user-id', generate.generateId(), ONE_MONTH_IN_MILLISECONDS); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* @flow */ | ||
import { getClientID, getMerchantID } from '@paypal/sdk-client/src'; | ||
|
||
import type { | ||
Config | ||
} from './types'; | ||
|
||
export const getPropertyId = ({ paramsToPropertyIdUrl } : Config) => { | ||
// $FlowFixMe | ||
return new Promise(resolve => { | ||
const clientId = getClientID(); | ||
const merchantId = getMerchantID()[0]; | ||
const propertyIdKey = `property-id-${ clientId }-${ merchantId }`; | ||
const savedPropertyId = window.localStorage.getItem(propertyIdKey); | ||
const currentUrl = `${ window.location.protocol }//${ window.location.host }`; | ||
if (savedPropertyId) { | ||
return resolve(savedPropertyId); | ||
} | ||
let url; | ||
// $FlowFixMe | ||
if (paramsToPropertyIdUrl) { | ||
url = paramsToPropertyIdUrl(); | ||
} else { | ||
url = 'https://paypal.com/tagmanager/containers/xo'; | ||
} | ||
return window.fetch(`${ url }?mrid=${ merchantId }&url=${ encodeURIComponent(currentUrl) }`) | ||
.then(res => { | ||
if (res.status === 200) { | ||
return res; | ||
} | ||
}) | ||
.then(r => r.json()).then(container => { | ||
window.localStorage.setItem(propertyIdKey, container.id); | ||
resolve(container.id); | ||
}) | ||
.catch(() => { | ||
// doing nothing for now since there's no logging | ||
}); | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* @flow */ | ||
import { getClientID, getMerchantID } from '@paypal/sdk-client/src'; | ||
|
||
import { getUserIdCookie, setRandomUserIdCookie } from './cookie-utils'; | ||
import { getDeviceInfo } from './get-device-info'; | ||
import type { | ||
Config, | ||
TrackingType | ||
} from './types'; | ||
|
||
export const track = <T>(config : Config, trackingType : TrackingType, trackingData : T) => { | ||
const encodeData = data => encodeURIComponent(btoa(JSON.stringify(data))); | ||
|
||
const img = document.createElement('img'); | ||
img.style.display = 'none'; | ||
if (!getUserIdCookie()) { | ||
setRandomUserIdCookie(); | ||
} | ||
const user = { | ||
...config.user, | ||
id: getUserIdCookie() | ||
}; | ||
|
||
const deviceInfo = getDeviceInfo(); | ||
const data = { | ||
...trackingData, | ||
user, | ||
propertyId: config.propertyId, | ||
trackingType, | ||
clientId: getClientID(), | ||
merchantId: getMerchantID().join(','), | ||
deviceInfo | ||
}; | ||
|
||
// paramsToBeaconUrl is a function that gives you the ability to override the beacon url | ||
// to whatever you want it to be based on the trackingType string and data object. | ||
// This can be useful for testing purposes, this feature won't be used by merchants. | ||
if (config.paramsToBeaconUrl) { | ||
img.src = config.paramsToBeaconUrl({ trackingType, data }); | ||
} else { | ||
img.src = `https://www.paypal.com/targeting/track/${ trackingType }?data=${ encodeData(data) }`; | ||
} | ||
|
||
// TODO: this will add a new image EVERY time the 'track' method is called. There's no reason | ||
// to clutter the DOM like this. We should replace the old image. | ||
if (document.body) { | ||
document.body.appendChild(img); | ||
songz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* @flow */ | ||
|
||
export const TYPES = true; | ||
|
||
export type MuseServerConfigType = {| | ||
assetsUrl : string | ||
|}; | ||
|
||
export type MuseGlobalType = {| | ||
serverConfig : MuseServerConfigType | ||
|}; | ||
|
||
export type TrackingType = 'view' | 'cartEvent' | 'purchase' | 'setUser' | 'cancelCart'; | ||
|
||
export type CartEventType = 'addToCart' | 'setCart' | 'removeFromCart'; | ||
|
||
export type Product = {| | ||
id : string, | ||
title? : string, | ||
url? : string, | ||
description? : string, | ||
imgUrl? : string, | ||
otherImages? : $ReadOnlyArray<string>, | ||
keywords? : $ReadOnlyArray<string>, | ||
price? : string, | ||
quantity? : string | ||
|}; | ||
|
||
export type ViewData = {| page : string, title? : string |}; | ||
|
||
export type CartData = {| | ||
cartId? : string, | ||
items : $ReadOnlyArray<Product>, | ||
emailCampaignId? : string, | ||
total? : string, | ||
currencyCode? : string | ||
|}; | ||
|
||
export type CancelCartData = {| | ||
cartId? : string | ||
|}; | ||
|
||
export type RemoveCartData = {| | ||
cartId? : string, | ||
items : $ReadOnlyArray<{ id : string }> | ||
|}; | ||
|
||
export type PurchaseData = {| cartId : string |}; | ||
|
||
export type UserData = {| | ||
user : {| | ||
id? : string, | ||
email? : string, | ||
name? : string | ||
|} | ||
|}; | ||
|
||
export type IdentityData = {| | ||
mrid : string, | ||
onIdentification : Function, | ||
onError? : Function | ||
|}; | ||
|
||
export type ParamsToBeaconUrl = ({ | ||
trackingType : TrackingType, | ||
data : ViewData | CartData | RemoveCartData | PurchaseData | CancelCartData | ||
}) => string; | ||
|
||
export type ParamsToTokenUrl = () => string; | ||
|
||
export type ParamsToPropertyIdUrl = () => string; | ||
|
||
export type JetloreConfig = {| | ||
user_id : string, | ||
cid : string, | ||
feed_id : string, | ||
div? : string, | ||
lang? : string | ||
|}; | ||
|
||
export type Config = {| | ||
user? : {| | ||
id? : string, | ||
email? : string, // mandatory if unbranded cart recovery | ||
name? : string | ||
|}, | ||
propertyId? : string, | ||
paramsToBeaconUrl? : ParamsToBeaconUrl, | ||
paramsToTokenUrl? : ParamsToTokenUrl, | ||
jetlore? : {| | ||
user_id : string, | ||
access_token : string, | ||
feed_id : string, | ||
div? : string, | ||
lang? : string | ||
|}, | ||
paramsToPropertyIdUrl? : ParamsToPropertyIdUrl | ||
|}; | ||
|
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.
We were already ignoring this rule elsewhere.