Set the Visitor ID in Adobe Analytics through DTM - adobe-analytics

I'm trying to set the Visitor ID in Adobe Analytics through DTM.
Above the s_code I have:
var visitor = new Visitor("xxxx")
visitor.trackingServer = "xxx.xx.xx.omtrdc.net"
I've created a data element where the legacy code used to call the
Visitor.getInstance("xxxx");
and set the Visitor ID to %Visitor ID%
That's not working however, and my visitor ID is always just set to %Visitor ID% and obviously not reading any values. I'd really appreciate any input that someone can give me.
Thanks,
Mike

The Visitor ID pops s.visitorID and is in general related to visitor id, but is not the same as s.visitor which is what gets popped for the VisitorAPI integration. DTM does not currently have a built-in field for the s.visitor variable, so you will have to set it yourself within the config, either in the Library Management code editor (assuming you are opting to c/p the core lib and not the "Managed by Adobe" option) or else in the Custom Page Code section.
Since you are popping it in a data layer first, you can reference the data layer like this:
s.visitor = _satellite.getVar('Visitor ID');
NOTE: A separate potential issue you may have is with whether or not the Visitor object is available for your data element. Since data elements are the first thing to be evaluated by DTM, you will need to ensure that the VisitorAPI.js library is output before your top page DTM script include.
If this is a problem for you, or if you are wanting to host VisitorAPI.js within DTM, then you may need to adjust where you are popping that stuff. For example, place the VisitorAPI core code above the custom code as the first stuff within the data element, before:
var visitor = new Visitor("xxxx") visitor.trackingServer = "xxx.xx.xx.omtrdc.net
Or, don't use the data element at all. Instead, put the VisitorAPI code within the Adobe Analytics custom code or core lib section and pop all that stuff (aboove the s.visitor assignment). Or a number of other methods; point is, VisitorAPI stuff must be loaded before the data element can make use of it, same as it must be loaded before Adobe Analytics can make use of it.

So DTM is changing pretty fast and furious right now. They have a "Marketing Cloud Service ID" that works well. Before I used that, however, I did find a way to fix the code. Crayon Violent was right, as usual, that the problem was that the script wasn't available yet. I fixed this by putting the following code in between the VisitorAPI.js and the AppMeasurement stuff in the DTM managed library.
var aA = new AppMeasurement();
aA.visitorNamespace="companyname";
aA.visitor = Visitor.getInstance("companyname");
In addition, there were also some issues using my localhost for testing while trying to see if I had this correct or not. If you are having issues and think you have it correct, it may be worthwhile to elevate it to a different environment.

Related

Where is 's' object cached when using AppMeasurement in DTM

Omniture's basic page tracking function, s.t(), was not crafted for AJAX implementation. Unlike the onclick s.tl() function which has some gating instructions with s.linkTrackVars and s.linkTrackEvents, the s.t() function just perpetuates every cached property through to the next call and beyond.
I used to be able to use a ClearVars function to empty out all of the s object's attributes, but now that I am using AppMeasurement and letting DTM manage my implementation with the most updated version of that library—which I want to keep doing—I can't call the s object. I get the same "ReferenceError: s is not defined" that another person asked about here!.
I tried following Crayon Violent's instructions within that post, but I can't seem to find where DTM is stashing the cached values in between Adobe calls. This code:
window.s = new AppMeasurement();
lets me change/clear the attributes of s, but it's not the s I'm looking for. When I call the next AJAX s.t() function, all of the cached values are still there.
In my experience working with DTM and AA, there has been no end to bugs and caveats and workarounds with DTM's "native integration" of AA. This is why I have more or less decided that the best thing I can do is to either manage the lib myself or else treat AA as a 3rd party script (100% implement it through rules, just ignore that it's available as a tool).
As mentioned in my answer you linked, that line of code only works to expose the AA object in the window namespace if you are managing the library yourself. When you configure DTM to manage the library, it will instantiate AA object itself, and it will be buried within its own code (Honestly, I don't know why DTM did this, considering AA puts a number of other variables in the global namespace that DTM does nothing about).
AFAIK there is no documented way to reference it, but one thing I have found that seems to work for me - which as a disclaimer to cover my own arse I do NOT officially endorse: use at your own risk - is to use the following to get a reference of it:
var s = _satellite.getToolsByType('sc')[0].getS();
This uses getToolsByType method to get an array of the SiteCatalyst (Adobe Analytics) objects setup as tools in DTM. It does this by looping through _satellite.tools and comparing _satellite.tools[n].settings.engine to what you passed to getToolsByType.
Then I use [0] to get the first one in the array, under the assumption that there's only one configured (most people only do one). Then the getS() object pulls together the s object based on the settings in DTM. So from there, you can do things with it, including making use of s.clearVars()

Multiple Adobe Analytic tools in Adobe DTM - how do I only have one fire at a time?

I have multiple instances of Adobe Analytics in the same Adobe DTM web property. They all go to different report suites. I'd like to create a page load rule so that the data is only reported to one report suite for any given page. So far the page load rules that I have created are causing the AA data to report to all of the report suites. Does anyone have any idea to get them to only fire to one at a time?
Thanks,
Mike
It is possible to set DTM to suppress the call for an event based rule or direct call rule but currently it is not possible to do it with a page load rule within the DTM built-in interface.
Some things you can do:
1) Combine your Adobe Analytics instances into a single instance. Is there a particular reason you are using multiple instances of Adobe Analytics? I know you mentioned they are for separate report suites, but are they also for separate Adobe Analytics instances altogether? If not, is it because they are completely separate implementations with different variables and logic assigned for them? If the only thing different between them is report suite id, then you should combine them and write some logic to pop relevant report suite id(s) for s.account.
2) Make use of s.abort to suppress the calls. If your code version is H25.3+ or you are using AppMeasurement then you can set s.abort to true to make the next Adobe Analytics request (s.t or s.tl call) be cancelled. Note that this may only be feasible if your instances are all using separate namespaces.. if you are just outputting several instances of code all under the same namespace, you will have issues. Also, if you are doing that, then you may also have issues as far as variables carrying over to other instances. But in any case, basically within your page load rule you'd add a rule condition where criteria is Data:Custom and then you'd write js logic to determine which one(s) you don't want to pop and set [namespace].abort=true; for each of them. Then return true at the end to make sure the condition is always true.
Or, you can set s.abort=true; within the Custom Page Code section for each Adobe Analytics instance you want to suppress in the page load rule. There are various other methods for popping s.abort but hopefully you get the picture. Which one is best just depends on how all your stuff is actually setup.
3) Pop the Adobe Analytics tags as a regular tag instead of a Tool. Remove them as a tool and put them as a Javascript / Third Pary Tag within the page load rule. This includes the core lib code and anything else you may have in the Tool config section. This also means outputting the "trigger" (s.t call). Make a separate one for each one and then you can make conditions for them to pop.
To add to Crayon's answer, you can also choose a custom code implementation in the Library Management section of the tool configuration settings. You will have to paste in the s_code contents and check the box that says "Set report suites using custom code below"
Then, you can use whatever logic you want to set a variable in the code that directs data to the report suites.
if(document.location.href == "http://www.mypage1.com"){
s_account = "rsid_1";
}else{...}
To add to Brett's answer - with rare exception, I let Adobe manage the analytics file. However, you can use the customize page code section within the Adobe Analytics tool configuration to deploy plugins or set the report suite ID dynamically. Here's an example I commonly use:
var suiteid;
var enviro;
var getURL = window.location.href
// Set RSID based on URL
if (getURL.indexOf('myURL.com') != -1)
{
suiteid = 'rsidproduction';
s.linkInternalFilters = 'javascript:,mailto:,tel:,' + window.location.host;
enviro = 'prod';
}
else
{
suiteid = 'rsidstaging';
s.linkInternalFilters = 'javascript:,mailto:,tel:,' + window.location.host;
enviro = 'dev';
}
s.account = suiteid;
This is an easy way to dynamically change the RSID and keep the analytics file managed by Adobe. I also blogged about this here: Managing your RISD Dynamically

Response comments added to the wrong parent document

I have a view data source that uses a view key to access documents and show them in a repeat with var "posts". within the repeat I have a document data source with var "post" that gets's the the unid of the documents using posts.getUniversalID().
further down the repeat I have another document data source "newcomment" that is a response and take the parent id as: post.getDocument().getUniversalID()
below the newcomment data source I have an editbox and a submit button which saves the comment as a response to the "post" using newcomment.save()
Here is my problem
two people access the same xpage. personA enters the page and starts writing a comment to a post. in the same time personB creates a new post and submit it before personA submits the comment. What happens now is that the comments gets binded to the latest post and not to the post personA responded to.
I tried anothoher thing also, let's say there is 10 posts in that database. personA and personB access the xpages. personA start writing a comment to post number 8. at the same time personB creates two new posts in the database. when personA now submits the comment it seem to get bind to the same index which is now two posts up. but still index 8. which is ofcourse the wrong post.
If I change the repeat to "createControlsAtPageCreation" ie.e repeatControls=true the comment is attached to the correct post but then I run into another problem that the view is not updated to show the latest posts.
my repeat is wihtin a custom control that is loaded dynamically using the dynamic content control in extlib.
As information here is what I have found about the repeatControls settings
Setting the repeatControls property to true instructs the repeat control to create a new copy of its children for each iteration over the dataset.
When the Repeat control is configured with the property
repeatControls=“true” , it repeats its contents only once, at page load time
So my question here is that I do not understand what is going on. why is my comment attached to the wrong parent document? and is there a way I can prevent this and still have new posts displayed correctly
thanks for your help
Without the code it's a bit hard to imagine what exactly is going one here but this looks very similar to problem that I had with repeat control and value binding.
Long story short the problem was connecet to repeatControls property set to false. When it was like that data binding were working only for first element in collection - all data was somehow magically saved to this first object! I managed to get this working by using combination of dynamic content control rebuild and repeatControls set to true. Only then databindings were working property.
It seems like if You are repeating rendering only (and this is what repeatControls set to false do) the decoding phase of jsf lifecycle goes foobar.
Without your XSP markup, it's difficult to be absolutely definitive but it appears that you're app code is creating and persisting the datasources and components per row during page load - therefore increasing the overall size and complexity of the component tree also. You should alternatively try an approach that will lazy-load the datasource only when requested by the end-user (eg: edit / reply).
Refer to the XPages Extension Library demo application (XPagesExt.nsf) for examples that use such a dynamic approach. In particular, look at Core_InPlaceForm.xsp which demonstrates using the xe:inPlaceForm control within a xp:repeat. And also see Domino_ForumView.xsp which demonstrates using the xe:forumView and xe:forumPost controls to manage and visualize a hierarchical thread. Also consider the concurrency mode that best suits your requirements when it actually comes to saving any given post or comment (fail, createConflict, force, exception) and document locking for high contention situations. The above-mentioned controls all provide the highest level of dynamic control and datasource creation and destruction.
Please feel free to send me on a worked example database, where I can understand your exact use case - DM me or email me.

Access specific extension object data from page code

I'm trying to build an addon that will observe and collect XHR and image responses received on a page and make them available to page script (on that page) for further inspection.
In my 'http-on-examine-response' observer code, I push URLs I'm interested in, into an array for their associated window, into an object, something like this -
myWindowId = resp.outerWindowID+'-'+resp.currentInnerWindowID;
storedResponses[myWindowId].push(subject.URI.spec);
(I thought that approach may be better than using tab references to identify unique source windows)
The relevant arrays are updated automatically as any page makes a request.
I'd like to be able to query the relevant array from page script or a bookmarklet at any time.
Should I set up port.on..., or postMessage() communication between the page/bookmarklet, content script and extension, or use a pageMod to write the appropriate array directly to an unsafeWindow global object on the relevant page?
I couldn't figure out how to make a pageMod write a specific array to a specific page as soon as the new responses were observed.
Full source is here -
https://builder.addons.mozilla.org/addon/1064905/latest/
I think it's all working, apart from getting the data back on to the page.
With help from Wladimir Palant, I found that XPCNativeWrapper.unwrap() is defined and does what I needed from the SDK module context. It allowed me to set variables directly in a window from my addon.
More info about wrappers here -
https://developer.mozilla.org/en/XPCNativeWrapper

How to link a google apps script in a google site

I'm creating a google site for my company and I'm utilizing google apps scripts to do a little extra on the site. I would really like to link a script to a drop-down menu that I made. However, I can't figure out how to link the script. I know how to link a script just as a google gadget and as a stand alone link, but I would really like to have the script run when I click on an item from my drop-down menu.
For security reasons, Google don't let you put javascript in Google Sites.
They provide Apps Scripts instead, but as they work on an isolated world (on the server rather than the browser), its very tricky and has its ways.
Because its very different to standard page's javascript, you have to rethink your goal in terms of what Apps Scripts lets you do.
Google Apps Scripts lets you build an User Interface (using its yet experimental UI API) that can be visualized as a standalone script in a full page or inserted in a iframe in Sites. This means you won't have a dropdown menu overlaping your site: you need an static space to visualize your script's UI.
There is another more primitive way to "embed" your scripts commands in your site: use links. A link that fires a script, even with your own parameters, only to run de command, but without any UI. You can make a menu with options, each of them fires a script. But I'm not talking about dropdown menu.
About Google Apps Scripts User Interfaces
https://developers.google.com/apps-script/guide_user_interfaces
https://developers.google.com/apps-script/guide_gui_builder
https://developers.google.com/apps-script/service_ui
Not sure what you mean by "link the script", do you have code someplace else? By "link" it sounds like you mean to "Call" the code, with an event handler. I'll show you how to call a function with a ServerHandler triggered by either a GUI ListBox Change event or from a Button Click event.
In Google Apps Scrips (GAS) there are three methods to do GUI.
HTML Service - Much like plain HTML, you could insert HTML form and input tags.
UI Service - Much like java (as far as layout managers), see below.
GUI Builder - I suggest doing it manually first to better understand layout.
In Google Sites you can add most HTML directly without a script. The UI Service and GUI Builder will generate HTML form tags for you, and since there's rarely any reason to insert GUI elements unless you are executing some code you probably want to start with using these.
Here is a Drop-Down list examplewith some changes to show how a handler function can be called from multiple UI elements (which they call Widgets sometimes) and how to use the parameter:
function doGet(e) { // use doGet() & UiApp to make a canvas.
var app = UiApp.createApplication();
var doEvent = app.createServerHandler('doEvent').setId('doEvent');
var myList = app.createListBox().setId('myList').setName('myList');
myList.addItem('one'); // add items, I use single quote strings.
myList.addItem('two').addItem('three') // I know it looks weird.
// Scripts let you do this, by returning self for your convenience.
.addChangeHandler(
app.createServerHandler('doEvent')
);
app.add(myList); // Add element to GUI.
doEvent.addCallbackElement(myList); // Add to Event Handler.
app.add(app.createButton('Click Me').setId('myButton')
.addClickHandler(doEvent));
return app;
} // Simple DropDown by Jason K.
function doEvent(e) { // use split() if isMultipleSelect is true
var app = UiApp.getActiveApplication();
app.add(app.createLabel(
'List Value is ' + e.parameter.myList
+ ' from ' + e.parameter.source));
return app;
}
As far as troubleshooting, remember to add each element with app.add() and return app; at the end of doGet and each handler function.
Handlers execute a function like JavaScript onClick() or onChange() functions, most UI are not useful without handlers. ClientHandler are more efficient but ServerHandler do more, start with ServerHandlers and any simple functions can be converted to ClientHandlers for better performance. You can choose to space out your handlers or cram it all into one line-of-code, really a matter of personal preference however do assign it to a variable if you plan to use it for more than one GUI object. You may want to look up the different layout managers to make more fancy looking applications, or just use the GUI Builder. Also there use to be other create functions like app.createServerClickHandler() but I understand those were useless and are now deprecated so ignore any other references you find like that, however we do still use addChangeHandler() and addClickHandler() to the GUI elements themselves.
The setName() seems to be silly, it is only needed to set the parameter name (I hope they change that) so for now I suggest just setting it the same as the element id. I also made the Handler's variable name = its id = the event function name just to illustrate how they are all related.

Resources