Asynchronous Integration with Amp.ai

Steve Mask

Apr 25, 2019

Subscribe

In a previous post, Overview of Browser Integration with Amp.ai, we looked at how to integrate with Amp.ai using the Browser or JS client synchronously. In the synchronous, or blocking integration, the size of the script is about 25KB after compression. This isn't too large until you have multiple projects running on the same page. In this article, we will look at how to integrate Amp.ai asynchronously, or non-blocking way, for highly latency-sensitive applications and for scenarios where you may be running more than one project on a page at the same time. If you haven't done so already, go to amp.ai to signup for an account and create your first project.  This will give you the project key needed for the following steps and to begin viewing sessions.  Let's get started!

Integration Options

The table below highlights the pros and cons of each type of integration with Amp.ai.  Choose the integration that best meets your needs.

OptionProsCons
Synchronous
  • Clean and simple integration
  • Configuration only required if running multiple projects simultaneously
  • Latency (50 - 100ms)
  • Size - 96+ KB
Hybrid - Synchronously loads the asynchronous snippet
  • Clean and simple integration
  • Configuration only required if running multiple projects simultaneously
  • Latency (minimal)
  • Size - 1KB
Asynchronous
  • Copy/paste JS on page
  • Configuration required
  • Zero latency

Hybrid Integration

Integration

Place the following script in the <head> section of your page.

<script src='https://amp.ai/libs/snippet/<PROJECT_KEY>.js'></script>

Asynchronous Integration

Configuration

Configuration is the same as the synchronous integration but it is necessary to specify your project key here for asynchronous. Simply set an ampConfig object on the window Object as below.

window.ampConfig = {
  key: <YOUR_PROJECT_KEY>
};
Make sure to place this before the script tag (See Integration). 

See the Amp.ai-Browser Client Integration Document for detailed configuration options.


Integration

To integrate Amp.ai asynchronously, just place the following snippet in a script block in the <head> section of your page immediately after the configuration.

<script>
"use strict";!function(){window.ampInstanceNames||(window.ampInstanceNames={}),window.ampConfig.instanceName?window.ampInstanceName=window.ampConfig.instanceName:window.ampInstanceName="amp";var e={};if(Object.assign(e,window.ampConfig||{}),window.ampInstanceNames[e.key]=window.ampInstanceName,!window.ampInstanceNames||!window[window.ampInstanceNames[e.key]]){for(var n=window[window.ampInstanceName]={replay:[],config:e,v:"1.2.0",ts:(new Date).getTime()},a="observe decide log".split(" "),t=0;t<a.length;t++)!function(e){n[e]=function(){for(var a=arguments.length,t=Array(a),i=0;i<a;i++)t[i]=arguments[i];"decide"===e&&"function"==typeof t[t.length-1]&&3===t.length&&(t=[t[0],t[1],{},t[2]]),n.replay.push([e,t,(new Date).getTime()])}}(a[t]);var i=document,o=i.getElementsByTagName("script")[0],m=i.createElement("script");o.parentNode.insertBefore(m,o),m.type="text/javascript",m.src=e.scriptSrc||(e.domain||"https://amp.ai")+"/libs/"+(e.k... Event("AmpLoaded"));var e=n.config.key,a=window[window.ampInstanceNames[e]];if(a.config=Object.assign(a.config,n.config),a&&n.replay)try{a.config.set("replayTime",(new Date).getTime()-n.ts),n.replay.forEach(function(e){e[2]&&a.timing("requestReplay",{method:name,event:e[0],start:e[2]}).end(),a[e[0]].apply(a,e[1])}),a.config.set("replayTime",0)}catch(e){a.warn(a.error({name:"UNAVAILABLE",message:"Error replaying amp snippet"}))}}}}();
</script>


API Calls

Making API calls in an asynchronous integration is the same as with the synchronous integration. The snippet above will setup a replay queue and push any amp.observe and amp.decide calls into it. Once Amp.ai is finished loading, these events will fire off in the order they were received.

Decision-making

Getting a decision back from Amp.ai asynchronously requires a little different implementation than synchronously. In the synchronous integration, explained in the Overview of Browser Integration with Amp.ai blog article, we see that we receive the decision immediately from the call. In an asynchronous integration, we must wait for the decision in the callback function.

amp.decide('EventName', { ctaColor: ['red', 'green', 'blue']}, function(err, decision) {
  // take action on decision returned
  amp.utils.ready('#subscribeBtn', function(element) {
    element.style.backgroundColor = decision.ctaColor;
  });
});

The code above will send a decide event into a replay queue while Amp.ai is loading. When it has finished loading, all of the events in the queue will fire off in the order they were sent. Once it reaches the above decide event, the callback function will execute immediately with the decision. We may then check if the DOM element, that we want to take action on with the decision, is available. If it is, we set the background color of the button we are querying.  This ensures that we take action as soon as the Amp.ai script has loaded to better our chances of minimizing flicker for above the fold changes.

Summary

In this blog we looked at how to integrate Amp.ai with the Browser client asynchronously.  While similar to the synchronous integration, minor changes were needed around making decisions to achieve zero latency.  In the beginning, we spoke about integrating multiple projects at the same time.  In my upcoming blog, we will see how to integrate Amp.ai both synchronously and asynchronously for multiple projects.  This will enable you to run many projects simultaneously to further increase your throughput of tests that you are wanting to run to optimize your application and gain valuable insights for future tests as well.