Life with Adobe Launch 2/3: Make it scale with a Custom Extension

How to ensure a centralized and scalable data collection standard across websites with a Launch Company Extension

Lukas Oldenburg
9 min readDec 23, 2020

Part I covered the rocky history of Adobe Tag Management Systems (TMS). It also showed that Launch still has many of the scaling issues of its predecessor Dynamic Tag Management (DTM). Fortunately, Launch offers a way out: Custom Extensions. So if you have multiple sites and want them to adhere to a common tracking standard, such an Extension is a must. Otherwise: innovation freeze and data quality disaster.

The problem

Your organization has multiple websites and you want to change one thing globally in all of them. The only options that Launch offers without a Custom Extension (like DTM) are:

  • stuffing all sites into one property (slows down your site, makes logic within this one property more complex => high risk of side effects)
  • going through the tedious and error-prone land of copy-paste

This means you will:

  • either not innovate much or have only one or two sites benefit from that innovation
  • end up with bugs, broken or inconsistently collected data because you forgot/were too lazy to update X in property Y as well, or because property Z has an outdated version of Helper function Y because someone forgot to update that in the last global innovation round etc.
  • in the best-case scenario, you waste a lot of usually expensive and limited resources on copy-paste time

Furthermore, setting up the same global tracking standard in a new Launch property (e.g. for a new website) will be a painstaking exercise of “did I really not forget anything?” (and of course you will forget something).

In short, you you have the choice between broken data, stalled development, or wasted resources.

The way out

There is a way out though. It requires building your company’s own Custom Launch Extension. Architecture-wise, it is a beautiful and professional way of ensuring a global standard across multiple Launch properties. And even within one property, it can help considerably keeping things standardized.

Note that there is quite some initial effort, as building such an Extension requires useful skills which many TMS specialists nowadays (including myself) had not needed before. I will talk about this in Part III.

So what is a Custom Company Launch Extension?

There are public Extensions which you find under the Extensions “catalog” in any Launch property (e.g. the “Adobe Analytics Extension”), and there are private (Custom) Extensions which you build yourself and only work in your company (organization) account. You can make also a private Extension public (if you dare going through quite a process).

Any Extension extends Launch in the following way:

  • A main.js script is executed whenever the Launch library loads (so usually on every page). This and a configuration screen are the absolute minimum an Extension needs to have.
  • Any number of Rule Actions, Events, Data Elements or Conditions can be added to the Launch interface (if you list them in the extension.json configuration file) or simply made available via code (we e.g. only expose certain Data Elements to the interface).
Example of a Data Element provided by a Custom Extension. Yes, I also think it looks awful, but I don’t want to bill more time to the client for learning how to use Adobe’s Spectrum CSS. I think Adobe should provide some easy-to-use layout standard here or simply make Extension views inherit the Launch layout.

All the Extension code is shipped with the Launch library code, so you need not worry about obstacles like Custom Code for Click Listeners needing to get downloaded first after the click (see Part I). It also means you should carefully weigh how heavy your Custom Extension should be.

So while the approach to load all Custom Code from a CDN is too much on one extreme, shipping all Extension code with the library seems to be on the other extreme. Thus, don’t add stuff to the library that is not really a global (cross-site) requirement.

Examples, please: What is the Custom Company Extension used for?

In short, the Custom Company Extension holds everything that should be the same in any Launch property. Some examples from actual cases:

  • Most importantly, it provides a standardized way to transform and enrich the data layer: e.g. it adds several standard variables, generates fallbacks for missing variables or older data layer standards. A common example are URL-based variables (URL Path, PII-cleaned URL Query String and Referrer, standardized stripping of high-cardinality URL Parameters to avoid “Low Traffic” in reports etc.).
  • Just as important, it provides standard mappings of data layer variables to Adobe Analytics and some other tools. This is crucial because you want to make sure that e.g. the language code in eVar777 is always set and always in the same way no matter the website. Or that tracking parameters from email campaigns are always processed the same way into certain Success Events and eVars. You will thus also never have sites / sections without certain must-have variables anymore (e.g. country code, content language, URL-based variables, timestamps etc…). That is crucial because now, your Analysts can rely on certain variables to be always there for their segments and metrics.
  • It provides standardized definitions of Data Elements (again the example of content language). Generally the Extension decreases the need to rely on Data Elements. I avoid Data Elements as much as possible because they are a notorious problem for scale — you cannot rename them unless you change each and every reference to them manually.
  • It configures the loading logic for the Cookie Consent Manager (some websites need it, some don’t, some need to load it from a separate URL some need Consent Manager A, others need B etc.). It also harmonizes the meaning of both Consent Managers’ user consent status so that a user can move from a site with Consent Manager A to another one with B without having to give consent again. Lastly, it also automatically handles the Consent Manager usage tracking into the Data Layer and Adobe Analytics.
The Custom Extension’s configuration page allows to set property-specific settings for the Consent Manager as well as Analytics tracking features.
  • It provides standardized Conditions (e.g. “must be on any of the company’s production hostnames” / “has at least opted in to tracking” etc.) -> very nice because this way a Condition becomes a central module, and if the logic inside this Condition changes (e.g. a new hostname is added), all rules that use the Condition will automatically have the new definition. An enormous time-and-nerve-saver.
  • It provides standardized Events that all rules can use (e.g. “User changed Consent Manager settings” -> basis for evaluating whether a tag can now be fired). The same scaling niceness as for the Conditions apply here. When we e.g. introduced a new Consent Manager, we only needed to update the definition behind the “User changed Consent Manager settings” Event and did not have to update any of the many Rules which fired based on that Event.
  • It enhances Adobe Analytics tracking, e.g. by throttling requests so that there is at least one second after the Pageview to not have Hits out of order in the reports (remember that if Analytics receives two or more Hits in the same second, it orders them randomly which leads to useless Flow or Fallout Reports — a common problem especially with Consent Managers where Hits are usually queued and then fired all at once as soon as the user gives consent).
  • It provides global Helper Functions that can be used anywhere in Launch (e.g. to safely access a nested data layer variable or to get the current cookie consent status).
  • It provides certain (partially optional) auto-tracking logic like automated download/email/offsite/phone link click tracking (no, I don’t recommend the built-in Adobe Analytics download link tracking) or Page Load Time.
Page Load Time Tracking is enabled by default in this Extension with one click.
  • It standardizes Error Handling (JS errors are sent to Adobe Analytics).
  • It provides an Action to include a third-party script. This was so often needed at this client, but done very differently across properties, so there was a need for standardization here. It also saves us from using more Custom Code Actions.

So why does this scale again?

When we now do a change to the global standard, we just update the Extension code in one place and release a new Extension version. In the Launch properties, we do not have to go through the copy-paste atrocity anymore, we simply click “upgrade” in the Extension overview page and then publish (after testing of course ;)). No chance that you accidentally miss one of the copy-paste steps. No redundancy. No reliance on Custom Code.

Standardization is great. But does this not stifle flexibility?

So am I forced to do everything the way the Extension prescribes? What if I have a website where 95% should be like the standard, but there is a good reason for an exception for 5%? An example is a website on which the URL paths (not the query strings) are completely cryptic (e.g. “”) and different for each user session. So generating the URL-based variables according to the standard makes no sense reporting-wise and would result in a lot of “Low Traffic”.

Such site-specific exceptions can be taken care of with so-called “Pre-Extension” and “Post-Extension” modules. They can be configured directly in Launch without requiring an Extension upgrade. They are simply inside a Launch rule that loads on on all pages. This rule contains a Custom Code Action with two functions inside, let’s call them preExtension() and postExtension().

You can do it differently, but this is our logic to ensure both a global standard and site-specific flexibility.

After receiving the data layer event, the first thing any Extension Action does is calling the Pre-Extension function. Within that function, you can e.g. add mapping logic for data that is only used on a specific site. For example, if only the Careers Portal needs a “Job ID”, it would be a waste to have a global logic in the Extension for the Job ID. The info that the Extension should map Data Layer variable “” to eVar457 and prop17 can simply be added in the preExtension() function for this single website similar to the following: myExtension.additionalMappings={ “”: “eVar457, prop17” }.

The Post-Extension module makes it possible to add “last mile logic”, so after the Extension has finished processing the data layer data “ETL” and just before any data is effectively pushed to its destinations, e.g. Adobe Analytics variables. A typical case is Analytics-only logic, where the data layer should stay as it is, but some additional Adobe-specific stuff is needed (like a certain Success Event). For the site with the cryptic URLs, this could be the place where you override eVars for certain URL variables, e.g. cutting off the cryptic part.

This way, the standard can be enforced and the benefits of the Extension can be used without sacrificing flexibility.

New site? Give me 10 minutes, please!

Need to onboard a new site with the Consent Manager plus Adobe Analytics standard tracking, supporting all the standard variables generated by the Extension? This would have been at least a day’s work in the past, full of error-prone copy-paste exercises. Now it can be done in less than ten minutes:

  1. Add the Custom Extension and set the checkbox for the Consent Manager.
  2. Add one Extension-based Data Element called “Tech — ECID Cookie Consent Object”.
  3. Add the Experience Cloud ID Extension and insert the Data Element to the “Pre-Opt-In Approvals” field. Also paste the URL of the tracking server twice times into the “Tracking Server Secure” and “Marketing Cloud Server Secure” fields.
  4. Add the Adobe Analytics Extension and set the Report Suite IDs in it. No other Adobe Analytics configuration needed. No eVar/prop/Event mapping, no doPlugins.
  5. Add one rule which contains the Extension’s “Set global variables and fire Pageview” Action. Check the box in the Action to also fire the Adobe Beacon right afterwards.

If the website requires exceptions, you add a Custom Code action in that one mentioned rule to define the pre- and postExtension functions with your additional logic inside before the Extension Action from step 5. That’s it. A major decrease in setup work, and much harder to make a mistake.

There are different approaches to enforcing a company standard with a Custom Extension. This is just one example, certainly not the prettiest one. All I can say is that this Extension has helped stabilize the setup massively and made rolling out new websites a piece of cake — and most of all, we sleep better because we rarely experience the “did I really not forget to copy-paste anything?” fear anymore.


There are of course downsides: It is not as easy as before for people who are not familiar with Extension development to see what is actually going on in the code. Also the standardized mapping to eVars/props need to be made visibly clear in the Action Views, otherwise it is a black box (still a todo for me).

The entry hurdle for someone new to understand how our Launch setup works is thus higher. And you need a much wider skillset to build an Extension than what you usually need to manage a TMS. Most TMS folks including myself don’t/didn’t have these skills. But that’s the topic of Part III!



Lukas Oldenburg

Digital Analytics Expert. Owner of Creator of the Adobe Analytics Component Manager for Google Sheets: