Split payment/verification business intelligence analytics

Track verify now and verify later choices, image captures, image retake, and name changes, as well as virtual pageviews for every step in the new flow(s).
This commit is contained in:
Renzo Lucioni
2014-12-16 17:28:30 -05:00
parent cb7f725d2d
commit f2e83bf57f
10 changed files with 75 additions and 24 deletions

View File

@@ -22,16 +22,21 @@
},
sync: function( method, model ) {
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
var headers = { 'X-CSRFToken': $.cookie( 'csrftoken' ) },
data = {
face_image: model.get('faceImage'),
photo_id_image: model.get('identificationImage')
face_image: model.get( 'faceImage' ),
photo_id_image: model.get( 'identificationImage' )
};
// Full name is an optional parameter; if not provided,
// it won't be changed.
if ( !_.isNull( model.get('fullName') ) ) {
data.full_name = model.get('fullName');
if ( !_.isEmpty( model.get( 'fullName' ) ) ) {
data.full_name = model.get( 'fullName' );
// Track the user's decision to change the name on their account
window.analytics.track( 'edx.bi.user.full_name.changed', {
category: 'verification'
});
}
// Submit the request to the server,

View File

@@ -11,15 +11,22 @@ var edx = edx || {};
edx.verify_student.FacePhotoStepView = edx.verify_student.StepView.extend({
postRender: function() {
new edx.verify_student.WebcamPhotoView({
el: $("#facecam"),
var webcam = new edx.verify_student.WebcamPhotoView({
el: $( '#facecam' ),
model: this.model,
modelAttribute: 'faceImage',
submitButton: '#next_step_button',
errorModel: this.errorModel
}).render();
$('#next_step_button').on( 'click', _.bind( this.nextStep, this ) );
this.listenTo( webcam, 'imageCaptured', function() {
// Track the user's successful image capture
window.analytics.track( 'edx.bi.user.face_image.captured', {
category: 'verification'
});
});
$( '#next_step_button' ).on( 'click', _.bind( this.nextStep, this ) );
},
});

View File

@@ -11,16 +11,23 @@ var edx = edx || {};
edx.verify_student.IDPhotoStepView = edx.verify_student.StepView.extend({
postRender: function() {
new edx.verify_student.WebcamPhotoView({
el: $("#idcam"),
var webcam = new edx.verify_student.WebcamPhotoView({
el: $( '#idcam' ),
model: this.model,
modelAttribute: 'identificationImage',
submitButton: '#next_step_button',
errorModel: this.errorModel
}).render();
$('#next_step_button').on( 'click', _.bind( this.nextStep, this ) );
},
this.listenTo( webcam, 'imageCaptured', function() {
// Track the user's successful image capture
window.analytics.track( 'edx.bi.user.identification_image.captured', {
category: 'verification'
});
});
$( '#next_step_button' ).on( 'click', _.bind( this.nextStep, this ) );
}
});
})( jQuery );

View File

@@ -75,6 +75,11 @@ var edx = edx || {};
}).appendTo(form);
});
// Marketing needs a way to tell the difference between users
// leaving for the payment processor and users dropping off on
// this page. A virtual pageview can be used to do this.
window.analytics.page( 'verification', 'payment_processor_step' );
form.submit();
},

View File

@@ -9,7 +9,6 @@ var edx = edx || {};
edx.verify_student = edx.verify_student || {};
edx.verify_student.PaymentConfirmationStepView = edx.verify_student.StepView.extend({
/**
* Retrieve receipt information from the shopping cart.
*
@@ -68,9 +67,24 @@ var edx = edx || {};
* The "Verify Now" button reloads this page with the "skip-first-step"
* flag set. This allows the user to navigate back to the confirmation
* if he/she wants to.
* For this reason, we don't need any custom click handlers here.
* For this reason, we don't need any custom click handlers here, except for
* those used to track business intelligence events.
*/
postRender: function() {},
postRender: function() {
// Track the user's decision to verify immediately
$( '#verify_now_button' ).on( 'click', function() {
window.analytics.track( 'edx.bi.user.verification.immediate', {
category: 'verification'
});
});
// Track the user's decision to defer their verification
$( '#verify_later_button' ).on( 'click', function() {
window.analytics.track( 'edx.bi.user.verification.deferred', {
category: 'verification'
});
});
},
/**
* Retrieve receipt data from the shoppingcart.

View File

@@ -14,8 +14,8 @@ var edx = edx || {};
var model = this.model;
// Load the photos from the previous steps
$( "#face_image")[0].src = this.model.get('faceImage');
$( "#photo_id_image")[0].src = this.model.get('identificationImage');
$( '#face_image' )[0].src = this.model.get('faceImage');
$( '#photo_id_image' )[0].src = this.model.get('identificationImage');
// Prep the name change dropdown
$( '.expandable-area' ).slideUp();
@@ -37,12 +37,17 @@ var edx = edx || {};
},
retakePhotos: function() {
// Track the user's intent to retake their photos
window.analytics.track( 'edx.bi.user.verification_images.retaken', {
category: 'verification'
});
this.goToStep( 'face-photo-step' );
},
submitPhotos: function() {
// Disable the submit button to prevent duplicate submissions
$( "#next_step_button" ).addClass( "is-disabled" );
$( '#next_step_button' ).addClass( 'is-disabled' );
// On success, move on to the next step
this.listenToOnce( this.model, 'sync', _.bind( this.nextStep, this ) );
@@ -57,8 +62,8 @@ var edx = edx || {};
handleSubmissionError: function( xhr ) {
// Re-enable the submit button to allow the user to retry
var isConfirmChecked = $( "#confirm_pics_good" ).prop('checked');
$( "#next_step_button" ).toggleClass( "is-disabled", !isConfirmChecked );
var isConfirmChecked = $( '#confirm_pics_good' ).prop( 'checked' );
$( '#next_step_button' ).toggleClass( 'is-disabled', !isConfirmChecked );
// Display the error
if ( xhr.status === 400 ) {
@@ -77,14 +82,14 @@ var edx = edx || {};
}
},
expandCallback: function(event) {
expandCallback: function( event ) {
event.preventDefault();
$(this).next('.expandable-area' ).slideToggle();
var title = $( this ).parent();
title.toggleClass( 'is-expanded' );
title.attr( 'aria-expanded', !title.attr('aria-expanded') );
title.attr( 'aria-expanded', !title.attr( 'aria-expanded' ) );
}
});

View File

@@ -47,6 +47,9 @@
this.postRender();
}
).fail( _.bind( this.handleError, this ) );
// Track a virtual pageview, for easy funnel reconstruction.
window.analytics.page( 'verification', this.templateName );
},
handleResponse: function( data ) {

View File

@@ -262,6 +262,10 @@
var success = this.backend.snapshot();
if ( success ) {
// Trigger an event which parent views can use to fire a
// business intelligence event
this.trigger( 'imageCaptured' );
// Hide the capture button, and show the reset button
$( "#webcam_capture_button", this.el ).hide();
$( "#webcam_reset_button", this.el ).show();

View File

@@ -78,7 +78,7 @@
<div class="copy expandable-area">
<p><%- gettext( "You should change the name on your account to match." ) %></p>
<input type="text" name="new-name" id="new-name" placeholder=<%- fullName %>>
<input type="text" name="new-name" id="new-name" placeholder=<%= fullName %>>
</div>
</div>
</div>

View File

@@ -19,7 +19,8 @@
<script type="text/javascript">
var analytics = {
track: function() { return; },
pageview: function() { return; }
pageview: function() { return; },
page: function() { return; }
};
</script>
<!-- end dummy segment.io -->