I am looking to use Optimizely on a site where we will use Angularjs, but from what I understand, that will be difficult because the whole purpose of Angularjs is to not manipulate the DOM, and Optimizely works by manipulating the DOM.
Does anyone have any guidance toward documents as to how to make using these tools together possible? Perhaps a structure where I could create directives to help the tool work?
First, you need to make the "Activation Mode" of the experiment "Manual".
Then, to make Optimizely check if the experiment should run (ie meets the URL target) you need to call window.optimizely.push(["activate"])
. This tells Optimizely to do the same thing it would do on a normal full page load. So depending on your situation, you can call the optimizely api from a few different locations...
In the run method of the app when views load
This works when what your experiment changes isn't tied to dynamic pieces that angular might make after the view loads. The $routeChangeSuccess event won't work with activating Optimizely because it fires before there's any DOM to manipulate.
app.run(function run($rootScope){
$rootScope.$on('$viewContentLoaded', function() {
window.optimizely = window.optimizely || [];
window.optimizely.push(["activate"]);
});
});
A more explicit way is to call window.optimizely.push(["activate"])
just in the controllers or directives that will actually have experiments. This way you can control the exact timing of the activate, like after data is loaded. I prefer this method because, more often than not, you're going to have to call the optimizely API to log a custom event to log that the user completed the desired goal anyway, so if I'm doing that event tracking explicitly, I might as well activate optimizely explicitly. Here's a service I inject when I need to activate or log events...
(function () {
'use strict';
function Optimizely($window) {
$window.optimizely = $window.optimizely || [];
this.Activate = function () {
$window.optimizely.push(["activate"]);
};
this.TrackEvent = function (eventName) {
$window.optimizely.push(["trackEvent", eventName]);
};
}
angular.module('myApp').service('Optimizely', Optimizely);
}());
Usage in a controller...
function MyCtrl(Optimizely) {
Optimizely.Activate();
Optimizely.TrackEvent("my_goal_success");
}
Yes, but you'll need to use the Optimizely's Javascript API.
http://developers.optimizely.com/javascript/
For anything more in depth you could also look at doing your own bucketing and using custom dimensions
Own Bucketing Example: https://github.com/tomfuertes/gaab
Custom Dimensions Docs: https://support.google.com/analytics/answer/2709829?hl=en
Edit:
On a high level Optimizely is a front end abstraction to a system that buckets and manipulates the DOM. It's meant to be used by non-devs or devs who want to use the reporting piece. You can still get to the same thing if you're custom coding an angular app by writing your own bucketing, splits, and features with a separate analytics tool like GA. Sounds daunting but is fairly simple if you take a look at the gaab
sample code above.
I'm not sure how Optimizely works, but with Visual Website Optimizer there is a feature that allows us to add a variation using JS. We manipulate the content like so:
// get Angular scope from a known DOM element
e = document.getElementById('some-dom-id');
scope = angular.element(e).scope();
// update the model with a wrap in $apply(fn) which will refresh the view for us
scope.$apply(function() {
scope.campaign.headline = 'This is a headline.';
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With