Answers to frequently asked questions about at.js.
Although at.js replaces mbox.js, mbox.js will continue to be supported. However, for most people, at.js provides advantages over mbox.js.
Among other benefits, at.js improves page-load times for web implementations, improves security, and provides better implementation options for single-page applications.
The following diagram illustrates page-load performance using mbox.js versus at.js.
As illustrated above, using mbox.js, page content does not begin to load until after the Target call is complete. Using at.js, page content begins loading when the Target call is initiated and does not wait until the call is complete.
Many customers and consultants want to know the impact of at.js and mbox.js on page-load time, especially in the context of new vs returning users. Unfortunately, it’s hard to measure and give concrete numbers regarding how at.js or mbox.js influence page-load time due to each customer’s implementation.
However, if the Visitor API is present on the page, we can better understand how at.js and mbox.js influence page-load time.
The Visitor API and at.js or mbox.js have an impact on page-load time only when you are using the global mbox (because of the body-hiding technique). Regional mboxes are not impacted by Visitor API integration.
The following sections describe the sequence of actions for new and returning visitors:
The Visitor API is loaded, parsed, and executed.
at.js / mbox.js is loaded, parsed, and executed.
If global mbox auto-create is enabled, the Target JavaScript library:
The Visitor API is loaded, parsed, and executed.
at.js / mbox.js is loaded, parsed, and executed.
If global mbox auto-create is enabled, the Target JavaScript library:
For new visitors, when the Visitor API is present, Target has to go over the wire multiple times to make sure that Target requests contain Experience Cloud Visitor ID data. For returning visitors, Target goes over the wire only to Target to retrieve the personalized content.
at.js version 1.0.0 and later fires all the requests in parallel. Previous versions execute the requests sequentially, meaning the requests are put in a queue and Target waits for first request to complete before moving on to the next request.
The way previous versions of at.js execute requests is susceptible to the so-called “head of line blocking.” In at.js 1.0.0 and later, Target switched to parallel request execution.
If you check the network tab waterfall for at.js 0.9.1, for example, you’ll see that next Target request doesn’t start until the previous one has finished. This is not the case with at.js 1.0.0 and later where all the request basically start at the same time.
From a response-time perspective, mathematically, this can be summed like this
As you can see, at.js 1.0.0 will complete the requests faster. In addition, at.js requests are asynchronous, so Target doesn’t block page rendering. Even if requests take seconds to complete, you will still see the rendered page, only some portions of the page will be blanked out until Target gets a response from the Target edge.
The at.js 1.0.0 release makes it possible to load the Target library asynchronously.
To load at.js asynchronously:
The recommended approach is via a tag manager such as Adobe Launch or Adobe Dynamic Tag Manager (DTM). See the Add Adobe Target lesson of the Implementing the Experience Cloud in Websites with Launch tutorial for more information.
You can also load at.js asynchronously by adding the async attribute to the script tag that loads at.js. You should use something like this:
<script src="<URL to at.js>" async></script>
You can also load at.js asynchronously using this code:
var script = document.createElement('script');
script.async = true;
script.src = "<URL to at.js>";
document.head.appendChild(script);
Loading at.js asynchronously is a great way to avoid blocking the browser from rendering; however, this technique can lead to flicker on the web page.
You can avoid flicker by using a pre-hiding snippet that hides the page (or specified portions) and then reveals it after at.js and the global request have completely loaded. The snippet must be added before loading at.js.
If you are deploying at.js through an asynchronous Launch implementation, be sure to include the pre-hiding snippet directly on your pages, before the Launch Embed code, as described in the Add the Target Pre-Hiding Snippet section of the Implementing the Experience Cloud in Websites with Launch tutorial.
If you are deploying at.js through a synchronous DTM implementation, the pre-hiding snippet can be added through a Page Load rule triggered at the top of the page.
For more information, see How at.js manages flicker.
Adobe Experience Manager 6.2 with FP-11577 (or later) now supports at.js implementations with its Adobe Target Cloud Services integration. For more information, see Feature Packs and Integrating with Adobe Target in the Adobe Experience Manager 6.2 documentation.
Target provides several ways to prevent page-load flicker. For more information, see Preventing Flicker with at.js.
The at.js file is approximately 109 KB when downloaded. However, because most servers automatically compress files to make file sizes smaller, at.js is approximately 34 KB when compressed (using GZIP or another method) on your server and loaded as users visit your website. The compression settings on the server where you installed at.js determine its actual compressed size.
at.js implementations use a single library ( at.js), while mbox.js implementations actually use two libraries ( mbox.js and target.js). So a fairer comparison is at.js versus mbox.js and target.js
. Comparing the gzipped sizes of the two versions, at.js version 1.2 is 34 KB and mbox.js version 63 is 26.2 KB. ``
at.js is larger because it does a lot more DOM parsing compared to mbox.js. This is required because at.js gets “raw” data in the JSON response and has to make sense of it. mbox.js uses document.write()
and all the parsing is done by the browser.
Despite the larger file size, our testing indicates that pages load faster with at.js versus mbox.js. Additionally, at.js is superior from a security perspective because it doesn’t load additional files dynamically or use document.write
.
at.js currently uses parts of jQuery and thus you will see the MIT license notification at the top of at.js. jQuery is not exposed and it doesn’t interfere with the jQuery library you already have on your page, which might be a different version. Removal of the jQuery code within at.js is not supported.
No, if cross domain is set to x-only and Safari has third-party cookies disabled, then both mbox.js and at.js will set a disabled cookie and no mbox requests will be executed for that particular client’s domain.
To support Safari visitors, a better X-Domain would be “disabled” (sets only a first-party cookie) or “enabled” (sets only a first-party cookie on Safari, while setting first- and third-party cookies on other browsers).
Not on the same page. However, while implementing and testing at.js, you can run at.js on some pages and mbox.js on other pages until you’ve completely validated at.js.
Yes, you can use the VEC for your SPA if you utilize at.js 2.x. For more information, see Single Page (SPA) Visual Experience Composer.
Yes. You can also use mboxTrace for debugging purposes or your browser’s Developer Tools to inspect the Network requests, filtering to “mbox” to isolate mbox calls.
Yes, same as with mbox.js.
Target customers sometimes use cloud-based instances with Target for testing or simple proof-of-concept purposes. These domains, and many others, are part of the Public Suffix List.
Modern browsers won’t save cookies if you are using these domains unless you customize the cookieDomain
setting using targetGlobalSettings(). For more information, see Using Cloud-Based Instances with Target.
Yes, if you are using at.js version 1.2 or later. We strongly recommend that you keep current with the latest version, however.
The following examples are not necessary if you are using at.js version 1.2 or later.
Depending on how you use targetGlobalSettings, you might need to make additional modifications to the code after downloading at.js. For example, if you needed slightly different settings for your Target implementations on various websites and were unable to define these settings dynamically using custom JavaScript, make these customizations manually after downloading the file and before uploading to the respective website.
The following examples let you use the targetGlobalSettings()
at.js function to insert a code snippet to support IP addresses:
This example is for a single IP address:
if (window.location.hostname === '123.456.78.9') {
window.targetGlobalSettings = window.targetGlobalSettings || {};
window.targetGlobalSettings.cookieDomain = window.location.hostname;
}
This example is for a range of IP addresses:
if (/^123\.456\.78\..*/g.test(window.location.hostname)) {
window.targetGlobalSettings = window.targetGlobalSettings || {};
window.targetGlobalSettings.cookieDomain = window.location.hostname;
}
These message are not related to at.js functionality. The at.js library tries to report anything that can’t be found in the DOM.
The following are possible root causes if you see this warning message:
The page is being built dynamically and at.js cannot find the element.
The page is being built slowly (due to a slow network) and at.js cannot find the selector in the DOM.
The page structure that activity is running on has been changed. If you reopen the activity in the Visual Experience Composer (VEC), you should get a warning message. You should update the activity so that all the necessary elements can be found.
The underlying page is part of a Single Page Application (SPA) or the page contains elements that appear farther down the page and the at.js “selector polling mechanism” cannot find those elements. Increasing the selectorsPollingTimeout
might help. For more information, see targetGlobalSettings().
Any click-tracking metric tries to add itself to every page, regardless of the URL on which the metric was set up. Although harmless, this situation makes many of these messages display.
For best results, please download and use the latest version of at.js. For more information, see at.js Version Details and Download at.js.
tt.omtrdc.net is the domain name for Adobe’s EDGE network, used to receive all server calls for Target.
HttpOnly can be set only via server-side code. Target cookies, such as mbox, are created and saved via JavaScript code, so Target can’t use the HttpOnly cookie flag.
Secure can be set via JavaScript only when the page has been loaded via HTTPS. If the page initially loads via HTTP, JavaScript can’t set this flag. In addition, if the Secure flag is used, the cookie will be available only on HTTPS pages.
To ensure that Target can properly track users, and because the cookies are generated client-side, Target doesn’t use either of these flags.
Adobe Target executes all of its decisioning on the server side. This means that at.js fires a network request every time the page reloads or an at.js public API is invoked.
at.js tries to avoid pre-hiding HTML BODY or other DOM elements for an extended period of time, but this depends on network conditions and activity setup. at.js provides settings you can use to customize the BODY hiding CSS style, such that instead of blanking the entire HTML BODY, you can pre-hide only some parts of the page. The expectation is that those parts contain DOM elements that have to be “personalized.”
The at.js request is an async XMLHttpRequest
, so we execute the following steps:
Considering the above scenario, how often is the page’s content fully loaded and visible when at.js finally un-hides the element the activity is changing? In other words, the page is fully visible except for the activity’s content, which is then revealed slightly after the rest of the content.
at.js doesn’t block the page from rendering. A user might notice some blank regions on the page that represent elements that will be customized by Target. If the content to be applied doesn’t contain many remote assets, such as SCRIPTs or IMGs, everything should render quickly.
If a page is cached on a CDN that is close to user’s location, but not near the Target edge, that user might see some delays. Target edges are well-distributed across the globe, so this is not an issue most of the time.
Considering the following scenario:
The Target timeout is five seconds. A user loads a page that has an activity to customize a hero image. at.js sends the request to determine if there is an activity to apply, but there is no initial response. Assume the user sees the regular content of the hero image, because no response was received from Target regarding whether there is an associated activity. After four seconds, Target does return a response with the activity contents.
At this stage, would it be possible for the alternative version to be shown? So after four seconds, the hero image could be swapped out and the user could notice this image swap?
Initially, the image hero DOM element is hidden. After a response from Target is received, at.js applies the DOM changes, such as replacing the IMG and displaying the customized hero image.
at.js requires the HTML 5 doctype.
This syntax is:
<!DOCTYPE html>
The HTML 5 doctype ensures that the page loads in standard mode. When loading in quirks mode, some JS APIs that at.js depends on are disabled. Target disables at.js in quirks mode.