A couple of days ago Qwilr announced the release of our Beta, and as part of this launch we decided to run a little experiment on our unsuspecting audience. Using Optimizely, we did an A/B test of text on the welcome page in order to determine whether changes to the way we described the product would affect people clicking through to sign up (SPOILER ALERT: it did, but that’s not the focus here).
We had a small issue setting it up, which took a bit of digging through the Optimizely docs to work out, so I thought I’d write about it here for future reference. Optimizely worked great ‘out-of-the-box’. Even our business guru, Steve, was able to set up an A/B test, despite having nearly no technical knowledge (sorry Steve).
So if Optimizely attempts to manipulate the DOM now (as is the default behaviour) it would be forgiven for missing those one or two elements that Angular hasn’t yet injected. The solution that Optimizely suggests is to switch the snippet execution to manual triggering (if you created an Optimizely ‘campaign’ the included snippet code is set to automatically trigger on page load) and add a delaying function that waits until the portion of the page that you want to manipulate has loaded:
waitForDelayedContent = (selector, experiment, timeout, keepAlive) -> intervalTime = 50 timeout = timeout || 3000 keepAlive = keepAlive || false maxAttempts = timeout / intervalTime attempts = 0 elementsCount = 0 interval = setInterval () -> if ($(selector).length > elementsCount) if (!keepAlive) clearInterval(interval) experiment() elementsCount = $(selector).length else if (attempts > maxAttempts) clearInterval(interval) attempts++ , intervalTime waitForDelayedContent(".hero .button", () -> window.optimizely.push(["activate", 0123456789]) )
The above just defines a function that checks for the provided selector until a timeout. When it finds the selector in the DOM it executes the provided function, which in this case tells the Optimizely snippet to activate experiment ‘0123456789’. The selector is one of the elements that the Optimizely snippet would be manipulating.
This solution is a little hacky, as its correct behaviour is dependent on which selector is chosen. If you choose a selector that is injected well before other elements, then the delay will trigger the experiment’s start too soon, so some care is necessary. However, once we added in this delay the A/B test was working as expected… and it was on to the Beta announcement!