Merge pull request #11937 from zfox23/commerce_dataTracking1

Commerce Data Tracking: Iteration One
This commit is contained in:
Zach Fox 2017-12-06 14:07:04 -08:00 committed by GitHub
commit f88a72894d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 4 deletions

View file

@ -79,10 +79,12 @@ Rectangle {
if (result.status !== 'success') {
failureErrorText.text = result.message;
root.activeView = "checkoutFailure";
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemPrice, !root.alreadyOwned, result.message);
} else {
root.itemHref = result.data.download_url;
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
root.activeView = "checkoutSuccess";
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemPrice, !root.alreadyOwned);
}
}
@ -599,6 +601,7 @@ Rectangle {
sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
rezzedNotifContainer.visible = true;
rezzedNotifContainerTimer.start();
UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear");
}
}
RalewaySemiBold {

View file

@ -349,6 +349,7 @@ Item {
sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
rezzedNotifContainer.visible = true;
rezzedNotifContainerTimer.start();
UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear");
}
style: ButtonStyle {

View file

@ -48,6 +48,11 @@ Rectangle {
if (root.activeView !== "walletSetup") {
root.activeView = "walletSetup";
commerce.resetLocalWalletOnly();
var timestamp = new Date();
walletSetup.startingTimestamp = timestamp;
walletSetup.setupAttemptID = generateUUID();
UserActivityLogger.commerceWalletSetupStarted(timestamp, setupAttemptID, walletSetup.setupFlowVersion, walletSetup.referrer ? walletSetup.referrer : "wallet app",
(AddressManager.placename || AddressManager.hostname || '') + (AddressManager.pathname ? AddressManager.pathname.match(/\/[^\/]+/)[0] : ''));
}
} else if (walletStatus === 2) {
if (root.activeView !== "passphraseModal") {
@ -173,7 +178,7 @@ Rectangle {
Connections {
onSendSignalToWallet: {
if (msg.method === 'walletSetup_finished') {
if (msg.referrer === '') {
if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
root.activeView = "initialize";
commerce.getWalletStatus();
} else if (msg.referrer === 'purchases') {
@ -701,12 +706,28 @@ Rectangle {
case 'updateWalletReferrer':
walletSetup.referrer = message.referrer;
break;
case 'inspectionCertificate_resetCert':
// NOP
break;
default:
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
}
}
signal sendToScript(var message);
// generateUUID() taken from:
// https://stackoverflow.com/a/8809472
function generateUUID() { // Public Domain/MIT
var d = new Date().getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
d += performance.now(); //use high-precision timer if available
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
//
// FUNCTION DEFINITIONS END
//

View file

@ -31,6 +31,10 @@ Item {
property bool hasShownSecurityImageTip: false;
property string referrer;
property string keyFilePath;
property date startingTimestamp;
property string setupAttemptID;
readonly property int setupFlowVersion: 1;
readonly property var setupStepNames: [ "Setup Prompt", "Security Image Selection", "Passphrase Selection", "Private Keys Ready" ];
Image {
anchors.fill: parent;
@ -67,6 +71,13 @@ Item {
anchors.fill: parent;
}
onActiveViewChanged: {
var timestamp = new Date();
var currentStepNumber = root.activeView.substring(5);
UserActivityLogger.commerceWalletSetupProgress(timestamp, root.setupAttemptID,
Math.round((timestamp - root.startingTimestamp)/1000), currentStepNumber, root.setupStepNames[currentStepNumber - 1]);
}
//
// TITLE BAR START
//
@ -730,6 +741,9 @@ Item {
root.visible = false;
root.hasShownSecurityImageTip = false;
sendSignalToWallet({method: 'walletSetup_finished', referrer: root.referrer ? root.referrer : ""});
var timestamp = new Date();
UserActivityLogger.commerceWalletSetupFinished(timestamp, setupAttemptID, Math.round((timestamp - root.startingTimestamp)/1000));
}
}
}

View file

@ -88,3 +88,56 @@ void UserActivityLoggerScriptingInterface::doLogAction(QString action, QJsonObje
Q_ARG(QString, action),
Q_ARG(QJsonObject, details));
}
void UserActivityLoggerScriptingInterface::commercePurchaseSuccess(QString marketplaceID, int cost, bool firstPurchaseOfThisItem) {
QJsonObject payload;
payload["marketplaceID"] = marketplaceID;
payload["cost"] = cost;
payload["firstPurchaseOfThisItem"] = firstPurchaseOfThisItem;
doLogAction("commercePurchaseSuccess", payload);
}
void UserActivityLoggerScriptingInterface::commercePurchaseFailure(QString marketplaceID, int cost, bool firstPurchaseOfThisItem, QString errorDetails) {
QJsonObject payload;
payload["marketplaceID"] = marketplaceID;
payload["cost"] = cost;
payload["firstPurchaseOfThisItem"] = firstPurchaseOfThisItem;
payload["errorDetails"] = errorDetails;
doLogAction("commercePurchaseFailure", payload);
}
void UserActivityLoggerScriptingInterface::commerceEntityRezzed(QString marketplaceID, QString source, QString type) {
QJsonObject payload;
payload["marketplaceID"] = marketplaceID;
payload["source"] = source;
payload["type"] = type;
doLogAction("commerceEntityRezzed", payload);
}
void UserActivityLoggerScriptingInterface::commerceWalletSetupStarted(int timestamp, QString setupAttemptID, int setupFlowVersion, QString referrer, QString currentDomain) {
QJsonObject payload;
payload["timestamp"] = timestamp;
payload["setupAttemptID"] = setupAttemptID;
payload["setupFlowVersion"] = setupFlowVersion;
payload["referrer"] = referrer;
payload["currentDomain"] = currentDomain;
doLogAction("commerceWalletSetupStarted", payload);
}
void UserActivityLoggerScriptingInterface::commerceWalletSetupProgress(int timestamp, QString setupAttemptID, int secondsElapsed, int currentStepNumber, QString currentStepName) {
QJsonObject payload;
payload["timestamp"] = timestamp;
payload["setupAttemptID"] = setupAttemptID;
payload["secondsElapsed"] = secondsElapsed;
payload["currentStepNumber"] = currentStepNumber;
payload["currentStepName"] = currentStepName;
doLogAction("commerceWalletSetupProgress", payload);
}
void UserActivityLoggerScriptingInterface::commerceWalletSetupFinished(int timestamp, QString setupAttemptID, int secondsToComplete) {
QJsonObject payload;
payload["timestamp"] = timestamp;
payload["setupAttemptID"] = setupAttemptID;
payload["secondsToComplete"] = secondsToComplete;
doLogAction("commerceWalletSetupFinished", payload);
}

View file

@ -33,6 +33,12 @@ public:
Q_INVOKABLE void bubbleToggled(bool newValue);
Q_INVOKABLE void bubbleActivated();
Q_INVOKABLE void logAction(QString action, QVariantMap details = QVariantMap{});
Q_INVOKABLE void commercePurchaseSuccess(QString marketplaceID, int cost, bool firstPurchaseOfThisItem);
Q_INVOKABLE void commercePurchaseFailure(QString marketplaceID, int cost, bool firstPurchaseOfThisItem, QString errorDetails);
Q_INVOKABLE void commerceEntityRezzed(QString marketplaceID, QString source, QString type);
Q_INVOKABLE void commerceWalletSetupStarted(int timestamp, QString setupAttemptID, int setupFlowVersion, QString referrer, QString currentDomain);
Q_INVOKABLE void commerceWalletSetupProgress(int timestamp, QString setupAttemptID, int secondsElapsed, int currentStepNumber, QString currentStepName);
Q_INVOKABLE void commerceWalletSetupFinished(int timestamp, QString setupAttemptID, int secondsToComplete);
private:
void doLogAction(QString action, QJsonObject details = {});
};

View file

@ -110,8 +110,10 @@
var filterText; // Used for updating Purchases QML
function onScreenChanged(type, url) {
onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1;
onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH_BASE) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH || url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
wireEventBridge(onCommerceScreen);
onWalletScreen = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1;
onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH_BASE) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH
|| url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
wireEventBridge(onMarketplaceScreen || onCommerceScreen || onWalletScreen);
if (url === MARKETPLACE_PURCHASES_QML_PATH) {
tablet.sendToQml({
@ -122,7 +124,7 @@
}
// for toolbar mode: change button to active when window is first openend, false otherwise.
marketplaceButton.editProperties({ isActive: onMarketplaceScreen || onCommerceScreen });
marketplaceButton.editProperties({ isActive: (onMarketplaceScreen || onCommerceScreen) && !onWalletScreen });
if (type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1) {
ContextOverlay.isInMarketplaceInspectionMode = true;
} else {
@ -322,6 +324,11 @@
} else if (parsedJsonMessage.type === "LOGIN") {
openLoginWindow();
} else if (parsedJsonMessage.type === "WALLET_SETUP") {
wireEventBridge(true);
tablet.sendToQml({
method: 'updateWalletReferrer',
referrer: "marketplace cta"
});
openWallet();
} else if (parsedJsonMessage.type === "MY_ITEMS") {
referrerURL = MARKETPLACE_URL_INITIAL;
@ -399,6 +406,7 @@
referrer: "purchases"
});
openWallet();
break;
case 'checkout_walletNotSetUp':
wireEventBridge(true);
tablet.sendToQml({