Search code examples
adobeadobe-analytics

Issue Updating DTM Pre-defined Data Element when Anonymous FUnction


If I have a pre-defined data element called "CS Test" as so:

return (function() { 
  var rvalue = "default custom script value from some data layer";
  return rvalue;
})();

I want to update the value of "CS Test" data element with a new value (e.g. "Updated Value") based on an Event Based rule. I can't get this to work? I understand from a previous post that when you explicitly call _satellite.getVar('Example'), the order of operations is instead:

  1. Look for the specified target for the type (e.g. path (js var) for type JS Object) and return that value
  2. Look for the satellite cookie and return that value
  3. Return the default value

So not sure how to get around this since the data element code is always being executed and returning a value?


Solution

  • My point above is that updating the satellite cookie works but only until I call the last _satellite.getVar("CS Test") because it overwrites the satellite cookie with the value of the Data element code and returns the value of the Data Element.

    Okay so, I'm going to lay out a couple of different thoughts here, because you haven't been clear on what your data element function really does, what you are trying to achieve overall, etc.. so maybe some of this will both clarify how DTM works, and help you get to where you need to be.

    Setting the data element's cookie directly only "works" for updating it when DTM internally references it, e.g. (as mentioned) subsequent page loads. Also, I think (but have not tested) that it will work when using %data_element% syntax in the rule fields.

    But, as mentioned here (same link I posted in OP comment), when you explicitly make a call to _satellite.getVar() it forces your data element rule to be evaluated. This means that the code you have in there (your anonymous function) will get executed, and do whatever it does.

    And it sounds like maybe you are wanting DTM to somehow execute it, but selectively ignore some of it. Well, that's not possible for DTM to do. If you want something like that to happen, then you must rewrite your anonymous function to accommodate doing something like that. But I'll get back to this in a moment, because first I want to step back and ask..

    Why are you even using _satellite.getVar() right after writing the cookie anyway? The point of writing directly to the cookie is that you bypass the data element. More importantly, you already have the value, because you just set the cookie with it.

    So, maybe you just consolidated your code for the sake of example, and that subsequent .getVar() call is in a separate codebox or otherwise outside the scope of where you set the cookie.

    As mentioned, when you make an explicit call to .getVar(), DTM's order of operations for returning a value is

    1. Evaluate the data element. This means your anonymous function will execute. If this returns a truthy value, that's what you get. If it does not return a truthy value..

    2. If it is a persistent data element, DTM looks for the _sdsat_[data element name] cookie. If it exists (and has a truthy value), that's what you get. If it does not, then..

    3. Return the value you specified as a default value in the data element config (or undefined if you didn't specify anything)

    So again, I'm kinda shooting in the dark here, because I don't know the details of your data element and ultimate goal with it, but it sounds to me like you want to be able to call .getVar() but have the order of operations be like how DTM does it on page load (1 and 2 are reversed). Well, DTM doesn't have a built-in way to do this. It would be nice if Adobe added options in the data element config to specify order of operations, since clearly it behaves differently, depending on how the data element is referenced (be it by DTM itself or by you). But they don't have that at this time.

    So, if that is what you want, then you need to Restructure your anonymous function to behave more like DTM behaves with persistent data layers. Basically, add code to it that looks for the cookie for the default value of rvalue, then fall back to what you have now. This should then allow you to make explicit calls to .getVar(), because now your anonymous function, which gets executed first, will first look for the cookie value.

    Another option may be.. assuming that all this code (namely, the troublesome subsequent .getVar() call) is within the same rule, but for whatever reason is outside the scope of where you set the cookie in the first place (e.g., in a separate codebox), you can set the value to a different, on-the-fly created data element and then reference that instead. The benefit of doing it this way instead of just reading the cookie is that it exposes it to a data element so that you can also use %data_element% syntax (from the place where you set it, moving forward) if you need to.

    Update:

    Okay so from followup comments, I was playing around with DTM, and it looks like you can do the following, which may be what you are looking for.

    Page scoped persistence

    So for example in the predefined data element, you can have something like this:

    return function(rvalue) { 
      _satellite.data.customVars._defaultRvalue = 
        rvalue
        ||
        _satellite.data.customVars._defaultRvalue
        ||
        "default custom script value from some data layer"
      ;
      return _satellite.data.customVars._defaultRvalue;
    }
    

    Then, to get the current value, you'd do this:

    _satellite.getVar('data_element')();
    

    That will return the current value or "default[..]" if there is none.

    Then, if you want to set a new value, you can do this:

    _satellite.getVar('data_element')('new value');
    

    This will return "new value", and if you make subsequent calls (page scope):

    _satellite.getVar('data_element')();
    

    It will continue to return "new value".

    Example Scenario:

    _satellite.getVar('data_element')(); // initial page load, returns "default[..]"
    _satellite.getVar('data_element')('foo'); // returns 'foo'
    _satellite.getVar('data_element')(); // returns 'foo'
    _satellite.getVar('data_element')('bar'); // returns 'bar'
    _satellite.getVar('data_element')(); // returns 'bar'
    

    Note: This is only works for the duration of the page. If you need it to persist from page to page, you will need to instead set and draw from a cookie. Do NOT use the _sdsat_[data_element] cookie, because the function itself is stored in the cookie.

    Session+ Persistence (persisting from page load to page load)

    So for persisting it across a session, from page to page, you can do this for example:

    return function(rvalue) { 
      var rvalue=
        rvalue
        ||
        _satellite.readCookie('rvalue')
        ||  
        "default custom script value from some data layer"
      ;
      _satellite.setCookie('rvalue',rvalue);
      return _satellite.readCookie('rvalue');
    }
    

    Example Scenario:

    _satellite.getVar('data_element')(); // initial page load, returns "default[..]"
    _satellite.getVar('data_element')('foo'); // still on same page, returns 'foo'
    _satellite.getVar('data_element')(); // still on same page, returns 'foo'
    // reload page or go to new page:
    _satellite.getVar('data_element')(); // new page: returns 'foo'
    _satellite.getVar('data_element')('bar'); // returns 'bar'
    // reload page or go to new page:
    _satellite.getVar('data_element')(); // new page: returns 'bar'
    

    Note: A major caveat about doing this is that because you are effectively making the .setVar method a wrapper for a function, you will not be able to reference it in form fields in a rule with %data_element% syntax. Well, you can, but it will not give you what you want. In my testing, it returns a stringified version of the function itself, but who knows how else it may react, depending on browser/version. Just don't do it.