Expand my Community achievements bar.

s.apl in adobe analytics implementation vs Web SDK

Avatar

Level 4

Hi all, in the existing adobe set up we use the s.apl plugin to populate s.events. It is very handy as you put conditional statements and its easy to structure the events. In Web SDK, it seems like, we have to set each every single event separately and attach conditional statement for each event. Example below.

 

Question - does anyone have a way to replicate the same s.apl functionality in Web SDK set up ? Thank you.

 

function anon() {
  var events = s.events;
  try {
    if (window.dataLayer.instruction) {
      var reference = Bootstrapper.data.resolve(60351);
      var timeTaken = Bootstrapper.data.resolve(60382);
      var instructionType = Bootstrapper.data.resolve(67045);
      events = s.apl(events, "purchase", ",", 1);

      if (timeTaken > 0)
        events = s.apl(
          events,
          "event108=" + timeTaken + ":" + reference,
          ",",
          1
        );
      switch (instructionType) {
        case "add_cash":
          events = s.apl(events, "event75=1:" + reference, ",", 1);
          events = s.apl(events, "event88:" + reference, ",", 1);
          break;
        case "withdraw_cash":
          events = s.apl(events, "event76:" + reference, ",", 1);
          events = s.apl(events, "event77:" + reference, ",", 1);
          break;
        default:
          break;
      }
    }
  } catch (e) {}
  return events || "";
}

 

vs 

 

xdm._experience.analytics.event101to200.event108.id = 

if (window._dl.instruction) {
  var reference = Bootstrapper.data.resolve(60352);
  var timeTaken = Bootstrapper.data.resolve(60389);
  var instructionType = Bootstrapper.data.resolve(67043);

  if (timeTaken > 0)
    events = s.apl(
      events,
      "event108=" + timeTaken + ":" + reference,
      ",",
      1
    );
  }

// Above needs to be done very single event 

 

15 Replies

Avatar

Community Advisor and Adobe Champion

To be honest, I don't bother with most of the plugins, I just append using simple JS (I am using App Measurement currently).

 

In AppMeasurement, I just do:

s.events = s.events ? s.events + ",event1=" + someVariable : "event1=" + someVariable;

Basically, this is a short form IF Statement... I check if s.events is populated with anything, if it is, then I take the existing value of s.events and add my delimiter (,) and the new event I want to push (adding the numeric value if needed, or just a simple ",event1" if not)... and if there is no event data, then I just set s.events to my event (without the delimiter)

 

 

So instead of using a plugin, can you not use a similar simple JS function to append the values together?

If the shortform notation is confusing, you can break it out into a long form IF statement, which I can see you are already familiar with as per your example.

Avatar

Level 4

@Jennifer_Dungan  what about the Web SDK ? There are plenty of options in the appMeasurement, but it seems like in the web sdk we have to set each event separately. ie, you can't simply append and return one events variable.

Avatar

Community Advisor and Adobe Champion

No, you're right.. I thought that maybe you were trying to use the append to concatenate the serialization values...  and that you wanted a literal "event108" as part of that serialization....

 

No, as far as I am aware, all events do have to be set separately... the s.apl can be used to append any values technically... since you had the 

xdm._experience.analytics.event101to200.event108.id

I figured this was already there..

 

 

So, are you asking how to create an appended event list in WebSDK, rather than setting the events into the schema?

 

 

First off, do you have any needs or plans to use CJA in the future? Because if you are just switching your technology to use WebSDK, but don't actually need the proper SDK Schema, there is the option to send data as is, in Analytics format, using the "analytics" field group.

 

https://www.youtube.com/watch?v=D9eouvCtNRU

 

You can continue to send all your data with the "prop1", "eVar1", "events", etc designations... and these will be automatically mapped to your analytics instance.

Avatar

Level 4

Thanks for the above. I am trying to implement the setup hoping that it will be used for CJA (this use case is being considered). 

 

I guess the question is whether to use the direct mapping

xdm._experience.analytics.event101to200.event108.id = (function anon() {
  if (window._dl.instruction) {
    var reference = Bootstrapper.data.resolve(60352);
    var timeTaken = Bootstrapper.data.resolve(60389);
    var instructionType = Bootstrapper.data.resolve(67043);

    if (timeTaken > 0) return timeTaken + ":" + reference;
  }
})();

 

OR 

 

push everything as is in adobe currently into data._adobe.analytics properties. 

Franc_G_0-1732543190018.png

 

 

@Jennifer_Dungan if I understand correctly, you are implying that the CJA requires direct mapping ?

Avatar

Community Advisor

HI @Franc_G 

tbh, lately I am only using the second approach. The schema Adobe came up with to fill the AA object is an example how you can completely overengineer stuff.

 

So, with the Web SDK "Update Variable" action, you can define many things like with the old App Measurement interface, BUT you can also have a piece of custom code which lets you define and work with your dedicated "s" object.

bjoern__koth_0-1732544091282.png

 

content.__adobe = content.__adobe || { };
content.__adobe.analytics = content.__adobe.analytics || { };
let s = content.__adobe.analytics;

s.prop99 = "hello";
s.eVar10 = "world";
s.events = "event10";
// not more s.linkTrackVars or s.linkTrackEvents

 

My approach is

  • create a Web SDK data variable for Analytics
  • have a central rule with a Web SDK "update variable" that triggers on my page view AND interaction events that first clears existing data and sets the commonly to be sent data
  • in my page view / interaction rules
    • have an Web SDK "update variable" action that sets the event-specific data
    • have a Web SDK "send event" action that sends the Web SDK variable as data
Cheers from Switzerland!


Avatar

Community Advisor and Adobe Champion

I think @bjoern__koth had some great insights here.... 

 

If you are planning on potential CJA, most documentation states it would be better to have to have the "proper schema"... but I have also heard people recommending to use your own custom schema even with CJA... so I don't know what is the best approach there.

 

For AA, particularly if you are in the process of switching to WebSDK, the second approach (i.e. keeping your AA data in the same format and naming conventions you are used to) will make the transition less painful. Also, sending data to XDM Stream format then mapping back to AA has a lot of potential complications, and more potential for failure points... it will also make testing a lot harder, as you cannot see the final result in the debugger tool...

 

Even IF I was going to be doing CJA, but keeping AA, I would very likely consider keeping AA in the analytics format and sending the same data again in XDM for CJA....  yes, this would essentially duplicate data / make the JSON object larger... but I think it would be worth it for testing implementations alone.... and odds are, with CJA not being tied to the same "prop", "eVar", etc naming conventions, there is likely going to be some changes / updates / cleanup etc in the transition to CJA... so keeping it separate so that each product has it's own evolution.

 

When the JSON is data driven, I really don't see any issue with taking value X, and adding it to multiple keys for different uses (one for AA, one for CJA)... I mean aside from the request size...  But if you forget to map some data from XDM to AA, it might be months before you discover the issue...  and it's not like you can go back in time to fix it... 

Avatar

Level 4

@Jennifer_Dungan thanks for the above. The direct mapping is definitely more work AND much more prone to errors. Funny enough, I have assumed that this is the only way for the events to work correctly. I guess there is another way to do that - a middle ground of some sort.

From my perspective, a product string will be the most challenging to do in terms of the direct mapping. Whenever, we have a product string set (with all the events, eVars and props), THEN we should use the data._adobe.analytics properties. Otherwise, the pain and the misery will prevail at some point.

Avatar

Community Advisor and Adobe Champion

Well technically, using the JSON to break the content out into a structured format isn't in itself prone to errors... but ensuring it's all mapped correctly is.... I don't know about WebSDK in the Adobe Platform Debugger, but seeing post-processed data for AA has been broken for months (at least with client side AppMeasurment, but I suspect for all).... at least I can see the values that are being set to my specific dimensions (and since I don't use processing rules on web, I know that what I see is what I get)... I don't know how I would ensure that with WebSDK....

 

But I definitely agree with the "more work" assessment... 

Avatar

Level 4

Apologies, mistake in the code. Can't edit the post for some strange reason.

xdm._experience.analytics.event101to200.event108.id = (function anon() {
  if (window._dl.instruction) {
    var reference = Bootstrapper.data.resolve(60352);
    var timeTaken = Bootstrapper.data.resolve(60389);
    var instructionType = Bootstrapper.data.resolve(67043);

    if (timeTaken > 0) return timeTaken + ":" + reference;
  }
})();

Avatar

Community Advisor and Adobe Champion

Ah, ok, I was wondering about some of the original code, lol 

Thanks for the update.

Avatar

Community Advisor

Hi @Franc_G 

you can download the source of the plugin here https://experienceleague.adobe.com/en/docs/analytics/implementation/vars/plugins/apl

 

and with a tiny adjustment adapt it to e.g. work on your _satellite instance. 
I typically do that in a library loaded event custom code.

Instead of function apl, just do a _satellite.apl = function ... (essentially paste the whole block).


and use _satellite.apl() instead of s.apl()

 

works like a charm 

Cheers from Switzerland!


Avatar

Level 4

@bjoern__koth thanks for the above. If I understand it correctly, you are suggesting to load the apl plugin as custom code (as part of alloy.js base code) ? There is a custom code section, so we can put it in there. We have another property available, so will put it in there (see screenshot provided). 

 

Question - I am changing the execution context in here - function declaration vs expression. Anything to watch out for ? Thanks 

 

Franc_G_0-1732543848255.png

 

Avatar

Community Advisor

No, I am basically creating a functionality outside of the Analytics/WebSDK instance that can be reused everywhere.

The code itself has no depencies to AppMeasurement or the Adobe world.

 

If you want to not have any plugin dependencies, you can also write your own helper function

 

 

 

const apl = (list, item, delimiter) => {
    if (typeof list !== "undefined" && typeof list !== "string") {
        _satellite.logger.debug(">>> apl: list is of an unexpected type, ", list);
        return item;
    }

    list = list || "";
    delimiter = delimiter || ",";

    // If the list is empty, return the item
    if (list === "") {
        return item;
    } else {
        list = list.split(delimiter);
        if (!list.includes(item)) {
            list.push(item);
        }
        return list.join(delimiter);
    }
}

// testing
let list = "";
list = apl(list, "foo");
list = apl(list, "bar");

// 'foo,bar'

 

 

 

 

But as @Jennifer_Dungan mentioned, you can probably also just make your life easy and use her one-liner.

 

I just reuse the _satellite.apl every now and then in different other custom code locations.

Cheers from Switzerland!


Avatar

Community Advisor and Adobe Champion

Yeah, the Adobe provided plugins are really just JavaScript functions that run within the context of the s object... @bjoern__koth took that code, and with a few tweaks made it a function that could be run anywhere. 

 

Personally, I find a lot of the plugins a little "bloaty", and they try to do a lot of behaviours in one, that for the most part, most people don't need...  Hence, why if I am doing a concatenation, I will just write my own code (but I come from a developer background, so for me, it's easy to just write up the code when and where I need it...  and while yes, I could use a reusable function to pass in values, if something happens to the function and it breaks, stuff will break everywhere... so it's always a toss up...  For something like adding or appending a value to my events depending on if something already exists, the code is light enough that I didn't bother with a reusable function.

 

There are so many ways to approach this, and none of them are really right of wrong, just what works best for you.... both for using it, remembering how to use it, and maintaining it.

Avatar

Level 4

@bjoern__koth  @Jennifer_Dungan  thank you both for the valuable input, much appreciated