How to approach Product Finding Methods

Product Finding Method (PFM) is a valuable custom report used by online retailers to tie Cart Adds and eventual Revenue to how users found the product. Unfortunately, these reports are often poorly configured or misunderstood. It is one of the best use cases for using the Merchandising setting on an eVar, but Merchandising, as a concept, is one of the more complicated topics in implementation.

Primer on Merchandising

In order to tie that PFM value to an individual product, and not the overall visit or visitor, we need to use Merchandising. And since we may not know the eventual product at the time that we know the finding method (for instance, if a user is using internal search, at the time we know they are searching, we don’t know what product they’ll eventually land on), we need to use Conversion Syntax- meaning we set it like a typical eVar (instead of in the products string) but have to configure at what point that eVar should be tied (or “bound”) to a product. Take the following user experience into consideration, where eVar5 is used for Product Finding Methods:

PFMflow

In the above, if I did NOT use Merchandising, my report might look like this, where External Campaign gets credit for everything up until it gets overwritten by Internal Search– at which point Internal Search gets credit for everything, including the entire Purchase event.

PFMnoMerchReportIf I DO use Merchandising, the External Campaign gets credit for whatever happens to the product it was bound to- in this case, the Blue Wug. Then Internal Search gets bound to the Red Wug, and gets credit for whatever happens to the Red Wug product:

PFMwMerchReport

We have to be very careful with the binding events (the event that tells Adobe to take whatever value we currently have floating around for that eVar and stick it to the current product), though- merchandising eVars won’t get credit for anything that happens if they are not bound to any product, or if that product isn’t currently present. For instance, in the example above, if you pulled in Internal Searches as a metric in that report, you’d see no PFMs were getting credit for the Internal Search event- even though eVar5 is set on the same page as our search event. That’s because that “Internal Search” value for eVar5 is waiting until a “binding event” to attach it to a product before it will get credit for any metrics, and the “External Campaign” value for eVar5 only gets visibility into things that happen to the product it’s bound to (Blue Wug). No products on the Internal Search page means Conversion-Syntax Merchandising eVars get no credit for the Search event.

How to Plan Your Product Finding Methods

To design your PFM solution, start by thinking of the different ways a client can add an item to their cart. We’ll call these “add to cart location” and give that its own eVar. Typical scenarios are:

  • product details page
  • quick view
  • from wishlist
  • from order history
  • recommendation/cross sell modules

Next, figure out all the ways a user could get to any of those above scenarios. These are Product Finding Methods and should get their own eVar. Typical PFMs include:

  • internal search
  • external site (referrerss and natural search)
  • external campaigns (that take the user directly to the PDP)
  • internal promotion (eg, homepage hero banner)
  • browse (naturally navigating through the menu or breadcrumbs)
  • cross-sell
  • recommendations
  • wishlist
  • order history 

You’ll notice some of your cart add locations may also be product finding methods- that’s ok. Note that Products Detail Page is NOT a PFM- the Product Details page is specific to the product, which is the thing being found not the thing doing the finding.

Both of these eVars will need to be set up for Merchandising (this is set in the Admin console>Report Suites>Edit Settings>Conversion>Conversion Variables). For the Add to Cart Location eVar, since we know the product at the time we know the add to cart location, you can use “product syntax”.

eVar4PFM

This is preferable because it leaves little room for error and has the easiest configuration. Let’s say I’ve set eVar4 to be my “Add to Cart location” eVar. At the time my user adds any item to their cart, I would set eVar4 (often, you can just set it to the current page’s page type):

s.products=";sku1;;;;eVar4=PDP"
s.events="scAdd"

But for Product Finding Method, you often don’t know what product the value for our eVar will eventually bind to, so we need to set it to conversion syntax, and we need to carefully consider which events should bind the current PFM value to the current product. Generally, Product View (ideally a custom event, not prodView) and Cart Add suffice as binding events.

eVar5pfm

DO NOT set to bind on ALL events, as many events happen on your site where your PFM eVar doesn’t have a desirable value.

Next, to implement, we need to figure out where to set each of our PFM values. If you’re using a tag management system like DTM, you can often just piggy back on existing rules for many of your finding methods, but others may need to live in global logic (like in your s_code). See below for a possible configuration.

internal search Set on internal search results page
external site Set in global logic- if no other PFM is present, and the user came from a domain other than your own
external campaigns Set in global logic, if s.campaign is set
internal promotion Set in global logic, if internal campaign eVar is set (or internal campaign query string parameter is present).
browse Set on all Product List Pages and Category pages
cross-sell Set when user clicks or clicks through on a cross-sell module
recommendations Set when user clicks or clicks through on a recommendation module
wishlist Set on Wish List page
order history Set on Order History page

Some folks manage PFM entirely in their s_code or in their (global DTM tool settings) based on whether other variables have been set (“if internal search term eVar has a value, set eVar5 to ‘internal search”‘). For instance, one client has something similar to this, in addition to setting their PFM eVar directly on certain pages (like their List Pages and Category pages, or certain microsites):

//easy way to get just the hostname of the referring site
   var a=document.createElement('a');
   a.href=document.referrer;
   s.refDomain=a.hostname;

if(!s.eVar5){ //if PFM not currently set on the page
   if(s.campaign){s.eVar5="campaign"} 
   else if(s.eVar10){s.eVar5="internal search"}
   else if(s.eVar23){s.eVar5="recommended product"} 
   else if(s.pageName=="My Account>Wishlist"){s.eVar5="my wishlist"}
   else if(document.referrer==""){s.eVar5="direct or bookmarked"}
   else if(s.refDomain.indexOf("mydomain.com")==-1){s.eVar5="external site"} 
 }
   else if(s.eVar15){s.eVar26="internal campaign"} 
}

Conclusion

Hopefully, this gives some ideas and examples for how to get valuable reporting on how users are finding and purchasing products on your site. I’d love to hear about potential scenarios or solutions I’ve missed!

An alternative to using CSS for Event-Based Rules

A lot of the magic that happens in DTM is based on CSS (cascading style sheets) and CSS Selectors (using the styles applied to HTML elements as a map to your site). Even if you have a data layer to avoid relying on CSS for your data elements, Event-based Rules still rely on CSS Selectors to figure out which elements to listen to. For instance, if I want DTM to listen for clicks on my blog menu, which looks something like this:

<li id="menu-item-82" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-82">
     <a href="http://digitaldatatactics.com/beaconParser/">Beacon Parser Tool</a>
</li> 

I might tell it to listen to link/anchor tags (“a” tags) that are within list items (“li” tags) that have a class of “menu-item”.  The CSS Selector for this would be “li.menu-item a”, so I might create this rule in DTM:

ebrCSS

This should work, BUT there are a few potential problems:

  • it relies on the CSS of my site staying the same, and on my ability to interpret CSS selectors to get one with the right level of granularity.
  • Developers wouldn’t know that Analytics is relying on that “menu-item” class, and they might change it without notice.
  • An implementation may have dozens of these Event-based rules, which could require a lot of time to set up and test.
  • Lastly, if I want to pass a value like “nav click:beacon parser” I have to figure out a way to dynamically grab the value “beacon parser” from the surrounding HTML.

There is an alternative: instead of relying on classes, we could work with developers to add another attribute to the elements we want to listen to. This attribute would be completely arbitrary- I’m going to use “data-track” for this post. So I might ask developers to add “data-track=’nav click'” to that element:

<li id="menu-item-82" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-82" data-track="nav click:beacon parser">
     <a href="http://digitaldatatactics.com/beaconParser/">Beacon Parser Tool</a>
</li>

Then in DTM, I could set up a rule that listens not to CSS, but for clicks on any item that has “data-track” on it:
ebrDatatrack

Or if I wanted, I could have this particular rule only fire on clicks where “data-track” started with “nav click”: “[data-track^=’nav click’]”.

This approach has some benefits:

  • Developers aren’t likely to accidentally change the ‘data-track’ attribute
  • Setting up rules in DTM doesn’t require deep knowledge of CSS
  • You don’t have to rely on the HTML around the element to provide dynamic values (like “beacon parser” in my example above.) Whatever values I want in my reporting, I can have put in friendly wording into my data-track attribute.

As well as a few potential downsides:

  • I’d need to get my developers to add this attribute to all elements I want to track.
  • I’d need some sort of management on the values of those attributes (I may want to document that we’re using “nav click” and keep some standards and consistency across how data-track is used across the site.)

Ultimately, for many clients, the benefits of having control and flexibility far outweigh the upfront work of adding those tags.

Hopefully this approach can provide a solution to some folks out there, or at least can serve as a starting point for discussing the different options for setting event-based rules. I’d love to hear about folks who have used this solution or other solutions to keep CSS selector dependency to a minimum!

How do I use DTM for a Single Page App?

The question of how to use DTM on Single Page Apps (SPAs) is a VERY hot item right now. By Single Page App, I’m referring to a full user flow contained on a single web page, so as to provide the user a more seamless experience. Often, these pages act like typical web pages, but they don’t always change URLs or load new resources. Many common web development technologies, such as Angular.js, Ember.js, and AJAX use SPA principles.

Unfortunately, there isn’t a single great answer for how to deploy DTM- it depends on many things. I’ll work through some of the options and the limitations to be aware of.

Suppressing Page View Beacons

Whatever method you take for tracking page views in a SPA, keep in mind most SPAs do have one true “page view” when the DOM first loads. If you are going strictly with the DCR or EBR route, you may need to suppress the initial page view beacon the Analytics tool will want to set by default. Otherwise, in the example below where the developers are firing a direct call rule on all page views, you’d get TWO beacons on the first page and 1 on all subsequent pages.

Picture1

Data Layer Considerations

You’ll need to make sure that whatever the sources of your Data Elements are (CSS selector, javascript objects, cookies…) have the correct values BEFORE your rule is triggered. I have an example site showing one way you might do this for a data layer (though you’ll need to look in the source code), but ultimately it’s going to depend on your site.

Variable Persistence

One last consideration is that once your Analytics object exists (as in, the “s” in “s.pageName”), variables set on it will continue to exist unless specifically overwritten. In most cases, you’d overwrite s.pageName with a new value so it isn’t a problem, but something like s.eVar5 may be set on the first beacon in your SPA, and not desired on subsequent beacons. You can use s.clearVars() to “refresh” your “s” object, but you have to make sure it fires at the right time- for example, after the beacon on Page A, but before DTM starts mapping Data Elements to variables for the beacon on Page B. How you do this will depend on the overall deployment method you choose.

Deployment Methods

1) Direct Call Rules

Perhaps the most straight-forward approach is to have developers fire a Direct Call Rule, like _satellite.track(“page view”) on every thing YOU consider a page view, whether it’s a fresh new DOM or not.

Advantages: Disadvantages: 
  • You have ultimate control over when a page view in considered a page view.
  • If you need to clear out variables between beacons (for instance, you set s.eVar5 in the first beacon in the SPA, and don’t want it in the second beacon), Direct Call Rules don’t provide a great place to use something like s.clearsVars(). There are some potential work-arounds, but none are ideal.
  • Developers need to add more DTM-specific code (satellite.track) to your pages.
  • Direct Call Rules don’t allow for extra conditions (like “fire THIS logic on pageA, and THAT logic on pageB”) in the interface.
  • Direct Call Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

2) pushState or hashChange

Many SPA frameworks, like Angular, use a certain flag to let the browser know the user is viewing a new “page”.

pushState

DTM can listen for this flag in an Event Based Rule using a pushState or hashChange condition.

ADVANTAGES: DISADVANTAGES: 
  • No additional code is needed- most SPA frameworks are already firing something DTM can listen to
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • Because you are listening for an event set by the framework, you have less control over timing. Updating a data layer BEFORE the “pushState” event is detected would be critical.
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

3) Custom Event EBR

Another option, which feels a bit like a blend of the first two options, is to use a Custom Event-based Event Based Rule (and no, that’s not a typo- it’s an EBR based on the JavaScript Concept of a Custom Event). It’s possible Developers are already using this Custom Event concept for their own code and purposes, and DTM can just listen for it… or you can have developers set one specific to our DTM needs by using something like my digitalData.userAction hack.

ADVANTAGES: DISADVANTAGES: 
  • You have a little more control over timing
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • May require more developer work- similar level of effort as DCRs
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

 4) (NEW OPTION!) “dataelementchanged” Event Based Rule

Just in the last few weeks, a new option emerged as part of the AEM Context Hub integration. This allows DTM to listen for changes to certain data elements- for instance, you could have a rule fire whenever the “pageName” has changed. My friends at 33 sticks have a great blog post about this already for more info.

ADVANTAGES: DISADVANTAGES: 
  • You have a little more control over timing
  • It’s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions
  • Requires careful consideration of when the data layer changes/loads
  • Event Based Rules don’t “stack”- if multiple rules have conditions that are met, multiple rules will fire.

Setting up an Event-based Rule that be fired directly like a Direct Call Rule

Update:
As proud as I am of this solution/workaround, it may be far less needed now that you can use the dataelementchanged  condition to fire an Event Based Rule. Instead of using custom events, you can just have DTM listen for when your pageName Data Element has changed. 

The current limitations

If developers want to fire a DTM rule directly from their code (say, they want to make sure a beacon fires only after their data layer is ready), typically they would fire a Direct Call Rule, with its very specific syntax: _satellite.track(“rule string here”). There are, however, some limitations to this method.

Direct Call Rules:

  • Don’t allow for multiple conditions (you can’t say “if _satellite.track(“cart add”) is fired AND the current page has “/products” in the URL“)
  • Don’t allow for multiple arguments (you can’t pass _satellite.track(“cart add”,”sku1″) to attach the added SKU to the rule)
  • Don’t allow for firing s.clearVars() before your rule sets up your analytics variables (to clear out variables from previous beacons on the same DOM).
  • Require very specific syntax- they MUST be “_satellite.track()”

And unfortunately, both Direct Call Rules and Event-based rules don’t “stack”- if a certain condition triggers multiple similar rules, each rule will fire its own beacon. This is different from Page Load Rules, where if multiple rules have conditions being met by the current page, they all wrap nicely into a single page view beacon.

An alternative

To get around some (but maybe not all) of these limitations, I’ve been playing with another possible option, where we use the Custom Event conditions of an Event Based Rule to accomplish nearly the same thing. After getting it set up, I can fire something like this:

digitalData.userAction("cart add","sku1")

…to fire an Event-Based Rule in place of a Direct Call Rule. There are a few things I need to do in DTM to make this digitalData.userAction work.

Set Up the Logic

First, I have to set up the logic in a Page Load Rule- set to fire on DOMReady (no need for it to be sooner)- that will merely hold the following as a Sequential Javascript Third Party Tag:

//make sure digitalData is defined to prevent errors
if(typeof digitalData=="undefined"){
  digitalData={}
}

//create fake DOM item to bind the event to
var fakeDiv = document.createElement('div');
fakeDiv.setAttribute('id', "dtmHolder");
fakeDiv.setAttribute('height','1');
fakeDiv.setAttribute('width','1');
fakeDiv.setAttribute('style','display:none');
document.body.appendChild(fakeDiv);

//define custom event
digitalData.userAction=function(n,details){

 document.getElementById("dtmHolder").addEventListener("dtmEvent", function(e) {
    console.info("Event is: ", e);
  })

  // First create the event
  var dtmEvent = new CustomEvent(n, {
    detail:""
  });

  jQuery("#dtmHolder").attr("detail",details)
  
  // Trigger it!
  document.getElementById("dtmHolder").dispatchEvent(dtmEvent); 
}

(Update: note that this code should not run before the DOM is created- it will create an error if you try to run it at page top because you are trying to append something to a body that doesn’t exist yet).
Now, whenever a developer fires digitalData.userAction(“string here), you can listen for that string as the Triggered Event Type in a Custom Event Event Based Rule. Obviously, you can alter the above code if you want a function named something other than digitalData.userAction.

Set Up an Event Based Rule

The rule will need to be bound to the CSs selector of the tiny fake div (“#dtmHolder”) we created for the custom event to bind to:

2016-04-20_12-38-12

You can create as many of these rules as you want, for whatever different strings you pass into digitalData.userAction()where the “triggered event type” reflects that string.

Pass Additional Info

If you want to pass a second argument ( e.g. digitalData.userAction(“cart add”,”sku1″)) I currently have that second argument  passing as a new attribute (“detail”) on the tiny invisible div, so you can access it off the “this” object directly in the rule:2016-04-20_12-41-52

You can give this a try at my ugly test site– open a developer console, turn on DTM debugging, and fire either digitalData.userAction(“cartAdd”,”sku123″) or digitalData.userAction(“pageView”) to see two example rules at work.

Run ClearVars

This opens the ability to run s.clearVars on s.t() beacons in cases where multiple beacons may be firing on a single DOM. (As a reminder, if you’re using the old DCR route, there are some hack-ish options for doing this- we call it daisy-chaining).

In an Event Based Rule, there IS a code block that runs before the Analytics tool, giving you a perfect opportunity to make sure you are starting with a ‘clean slate’ of variables: the Conditions Custom Code block. Just create a new Rule Condition with “custom” criteria, then put “s.clearVars()” in the code block, followed by “return true” (so that DTM doesn’t think some condition didn’t pass):

2016-04-20_12-52-49

You can also apply additional conditions, like “only fire this “cart add” rule on certain pages”, by adding more criteria under Rule Conditions.

Conclusion

I’m very open to suggestions and feedback on this- maybe we can crowdsource a better way, but for now, this seems to be a reasonable alternative to Direct Call Rules. Let me know what you think!

Using Charles Proxy for Analytics

Charles Proxy is a packet-sniffing tool often used by web analysts and developers to debug beacons being sent to Adobe. I find it has some advantages over other tools, even over the Adobe Debugger, because it isn’t looking at your javascript or your “s” object on your DOM, and isn’t tied to a specific browser window or page, but rather it looks at what traffic is actually being sent (and hopefully, successfully received) by Adobe, regardless of where or how it is sent.

charlesFullBeacon

This shows all the parameters (or variables) in your analytics beacon. Some very nice person put up a cheat sheet of how those parameters map to variables or are used in processing and reporting.

On top of looking at Analytics Beacons, I often use it to do the following:

  • Examine which DTM files are loading, and in what order.
  • Check that calls to other Adobe tools (Marketing Cloud ID Service, Target, Audience Manager) are happening in the right order, and with the right parameters.
  • Route traffic from a mobile device through my desktop to see analytics beacons from that device (see instructions below).
  • Use Tools>Map Local to use a file on my machine to replace one of my client’s pages in my browser (for instance, I could save the source of a client’s page, tweak it for my needs, save it to my desktop, and then use Charles Map Local to look at how that page would behave in place of the real one). This makes it easy to see how a client’s page acts when a DTM library is placed on it, or if certain code is removed.
  • Use Tools>Map Remote to replace a file on the client’s site with a file from elsewhere on the internet. Often, this is to swap one DTM library out for another. Sometimes, I do this just to purposefully break a file- if I’m curious how a site would behave without jQuery, I might use map local to say “replace the jQuery file with a file at blank.js” (which doesn’t actually exist, so it effectively just says “don’t load the jQuery file). I did this often enough, and got sick of even seeing 404 errors, I created a blank file specifically for replacing other files.
  • Get the full URL of a POST beacon, so I can use my beacon parser tool to split it out.
  • Save a session of Analytics traffic so you can send it to peers.
  • View the Headers and Cookies attached to a given beacon (at the bottom of a beacon, where you are viewing your params, switch from Query Params to either “Headers” or “Cookies”):
    charlesHeaders

Charles is free if you’re ok with seeing a long splash screen and having sessions limited in length; it’s 50 dollars for a personal license if you want no splash screen and unlimited session length (I bought mine many years and many updates ago, it was worth every penny).

Charles Proxy and I have a bit of a love-hate relationship. It is pretty much ALWAYS open on my machine. It makes many aspects of my job so much easier. But sometimes, it just… doesn’t work. Many folks use the Tools>Rewrite capability to replace just certain code on the page, but it rarely works for me. And getting all the certification set up to accurately track SSL traffic is tricky. So, below is my guide for all the steps I follow when setting up Charles on a new machine to make it ideal for the type of tasks I test to do:

Install it

I prefer the Beta version since it happens to work better with my certificates and such, but for most folks the normal download should do just fine.  After you install it, if you use Firefox, you’ll also want to download the Firefox extension- the easiest way is to go to Charles>Help>Install Mozilla Firefox Add-on. This is not needed for Chrome or the other common modern browsers.

Filter it

Charles captures ALL traffic sent from your machine to anywhere on the internet. It can be… comprehensive. I quickly find it to be too much information, and I use the “Include” tab in Proxy>Recording Settings to tell Charles to only show things relevant to my job. Below are the common ones (asterisks are wildcards):

  • “assets.adobedtm.com” will show all Akamai-hosted DTM files. (If you self-host, you’ll want to add that URL up to the folder that contains your scripts- in other words, stop just before it says “/satelliteLib-“. That way you see ALL DTM files, like your s_code file, not just your main library)
  • “*demdex.net” shows Audience Manager and Marketing Cloud ID calls (fun fact: the Marketing Cloud ID service uses technology gained from Adobe’s acquisition of Demdex).
  • “*.tt.omtrdc.net” shows Target calls
  • Whatever domain you capture your analytics tracking on. For instance, on this site, my non-secure beacons are sent to “jenniferkunz.d1.sc.omtrdc.net”. Make sure you include both the secure and non-secure domains. If in doubt, you may be able to check this by seeing what your s.trackingServer and s.trackingServerSecure variables are set to in your s_code.
  • Because I have many Analytics clients, I also include all the common domains for analytics tracking, but you may not want to do this because you’ll catch many beacons not relevant to your implementation:
    • “*.2o7.net” for non-RDC, non-CNAME implementations
    • “*.omtrdc.net” for RDC implementations
    • “*metric*” as the domain and “*/b/ss*” as the path, to capture a vast majority of CNAME implementations.

charlesInclude

Use “Sequence” Mode

Most folks use “Structure” mode for viewing beacons, where a panel on the left will show all traffic, broken down by domain:

charlesStructureMode

I used this for years before realizing how much more I like sequence mode, which offers a few benefits:

  • It shows things in the order that they occur (making it easy to spot things like “uh-oh, the marketing cloud ID service hadn’t responded by the time my beacon fired”
  • You don’t have to know the root domain of your beacons off the top of your head. Secure and non-secure beacons are shown alongside each other.
  • It makes it very easy to filter. I often filter by “b/ss” to show only Analytics beacons, but you could also filter by “v0” to see only beacons that set the s.campaign variable, or by “landing” to show only beacons that had a pageName including “landing”.
    charlesSequence

Get it working with SSL

By default, Charles can’t read traffic from secure sources- or it can only show them with encrypted values (generally useless for debugging). There is information on the Charles site about setting up SSL tracking, but it can be hard to know what it means for you.

First, you need to set up a Root Certificate on your machine, giving Charles control over how your machine handles SSL Certificates. Go to Help>SSL Proxying>Install Charles Root Certificate. Follow the prompts from your operating system, but keep a careful eye out for two settings:

  • From the Charles site (specific to windows): “The certificate must be imported into the “Trusted Root Certification Authorities” certificate store, so override the automatic certificate store selection.”
  • Ensure the certificate is set to “Always trust” (if you miss this setting first time around, and you’re on a mac, you can change it later by opening your keychain.

If you have Firefox, you’ll also need to install the certificate through Firefox. If you’ve installed the Charles extension, then within Firefox you should be able to go to Tools>Charles Proxy>Install Charles Root Certificate.  When given the option, click “Trust this CA to identify websites”.

All of this has gotten Charles primed to listen for SSL traffic, but you still need to tell Charles which specific sites it can listen to, by going to Proxy>SSL Proxying Settings>SSL Proxying and entering the domains of your SSL analytics traffic. I tend to have this list pretty closely match by list of overall traffic filters, mentioned above (eg: “*2o7.net”, “*omtrdc.net”, “assets.adobedtm.com”, and “smetrics.*.com”).

Use it for Mobile Devices

If you want to route your traffic from a mobile device through Charles, it’s fairly simple. Below are instructions for an iOS device… sorry Android users, you’ll need to google to find similar instructions). Your mobile device and your desktop will need to be on the same network (ie, same WiFi). If your desktop is on VPN, your phone will need to be too.

First, if you will be looking at secure traffic, you’ll need to install the Charles certificate to your device. On your device, go to http://www.charlesproxy.com/getssl and follow the prompt. Pretty easy.

Next, get your local IP address (hint: this is different from your overall IP address, and specific to within your network). Charles makes this easy- in Charles, go to Help>Local IP Address.  You may want to jot this down and close this window, because when you get things working, Charles will want to pop up another window you need to pay attention to.

Lastly, on your phone, open up your WiFi settings and scroll to the bottom. Under HTTP Proxy, select “Manual”, then under Server, enter the Local IP address you noted above. Under Port, enter “8888”. Then click Renew Lease.

charlesMobile

[update- September 2017): If you still have issues with SSL traffic and get a “SSLHandshake: Received fatal alert: unknown_ca” error, you may need to go into your device’s settings- Settings > General > About > Certificate Trust Testings – and make sure the Charles Proxy Custom Root Certificate is marked as trusted.

Don’t forget to switch this back to “off” and re-renew your lease when done. 

Now move out to your browser and do a simple test to see if traffic gets sent and shows in Charles. The first bit of traffic should prompt a Charles warning on your machine, asking you to Allow this traffic.  If you miss this setting the first time around, you can tweak it under Charles>Tools>Access Control Settings.

Troubleshooting

If after all of this, it isn’t working right, here’s a few things to try:

  • If you are on VPN, and Charles isn’t cooperating, try switching the order you do things in: perhaps by opening your VPN first, THEN Charles, or the other way around. Experiment. I
  • If Charles works in one browser and not in another, check your Proxy menu: are you set to capture traffic data both on your OS (and therefore Chrome), as well as Firefox?
  • If Charles is interfering with things like your email server, check out your Bypass Proxy settings.

 

 

Referencing “this” in Event-Based Rules

Not many people know you can pull information out about the element that an Event-Based Rule fires on, without any custom code. Let’s say I want to fire a rule on a link that looks like this, and I want to capture the domain of the link that was clicked in eVar3:

<div partner="adobe">
     <a href="http://www.adobe.com" class="partnerExit" alt="go to our partner Adobe" target="_blank">This is an example link.</a>
</div>

I would set my rule up to correctly fire on that link (with something like “a.partnerExit”), then for eVar3 I would put %this.hostname%, where “this” refers to “this thing that the rule fired on”.

I don’t have to have to do any custom code, or have a data element set up (in fact, data elements are NOT particularly useful at pulling out information specific to the element that fired an event-based rule.)

Putting this in the interface…

Would let me access…

Which would yield this…

%this.hostname% The domain of the link that was clicked www.adobe.com
%this.href% The full URL of the link that was clicked http://www.adobe.com/
%this.src% The source of the element that was clicked (works for images, not links) (Not applicable here.)
%this.alt% The “alt” value of the element that was clicked go to our partner Adobe.
%this.@text% The internal text of the element that was clicked This is an example link.
%this.@cleanText% The internal text of the element that was clicked, trimmed to remove extra white space This is an example link.
%this.className% The class of the element that was clicked (less handy in reports, but very handy for DTM troubleshooting) partnerLink

For more advanced “DOM-scraping” you may need to take to the custom code. I find jQuery often simplifies things greatly for this. For instance, in the above example, if I wanted to get the ID not of the anchor tag, but of the <div> that HOLDS the anchor tag, I could do this in the custom code:

Note that I remembered to also add it into s.linkTrackVars, since this is an s.tl beacon (DTM automatically creates s.linkTrackVars for any variables you configure directly in the interface, but can’t know which variables you are adding to the custom code section, so you must be sure to add them to linkTrackVars or linkTrackEvents yourself, or the s.tl() beacon will ignore those variables).

How to get a global “s” object in DTM

At this point in time, by default, DTM creates your analytics object (usually an “s”, as in “s.pageName”) with a local scope. This means it should be able to be referenced from any custom code blocks within DTM that are tied to your analytics tool. However, it would NOT be accessible from code on the page (or a developer console) or even non-analytics code blocks in DTM (like Third Party Tags). This can cause some pretty big problems if you aren’t aware.

sUndefined

 

 

 

To get around this, you need to define your own s object within your library. This does mean you can’t let DTM manage your library, but the change you need to make is pretty minor. You need a “Custom” configuration, and you’ll need to “Set report suites using custom code below” (since you’re essentially going to be overwriting the “s” object that DTM created, where it set your report suites for you.

configureScode

 

 

 

 

 

 

When you open the editor, add this code to the top:

s = new AppMeasurement();
if(_satellite.settings.isStaging==true)
{s.account="myDevSuite"}else{s.account="myProdSuite"}

Make sure to replace the “myDevSuite” and “myProdSuite” with the correct report suites- these should match what you have in the interface. This uses _satellite.settings.isStaging to detect the current library and set the appropriate s_code.

 

With that in place, you should be able to access the “s” object from anywhere in DTM or on your page.

UPDATE: Because of a current quirk in DTM where it looks for the H code version of your s.account, I recommend also setting this line, below the ones above:

var s_account=s.account

This should prevent any report suite confusion on s.tl beacons from Direct Call Rules and Event Based Rules.

Why do my Adobe Analytics numbers differ so much from my bit.ly stats?

Link shorteners like bit.ly, goo.gl, and t.co generally keep their own metrics for how many times users click through. Unfortunately, those numbers rarely match any other Analytic’s system, including Adobe Analytics. We’ve seen situations where the bit.ly number was as much as 10 times the analytics number. With such a big difference, both numbers look a little suspect. So, what gives?

Bots

First, there’s non-human traffic. Link shorteners’ numbers do not always account for whether the click came from a real live human being, or a bot. Goo.gle and bit.ly DO try to eliminate bot traffic, but the list they use to identify bots is likely different from the list Adobe uses (which is maintained by the IAB).
However, link shorteners are often used on twitter, and bot traffic on twitter is a whole different beast. Web bots generally crawl pages, sometimes searching for specific things. Adobe and the IAB keep a good list of the worst web-crawling bot offenders. But on twitter, the environment is more predictable (tweets, unlike webpages, can predictably be accessed/interacted with the same methods) and the actions bots perform are simpler: click, retweet, reply. This means many more “hackers” out there can create a bot with much less effort, and since they aren’t harming much, they fly under the radar of the IAB and other bot-tracking organizations.
I found a book, “TWITTER: The Dark Side – Does Bit.ly Enable a Massive Click Fraud?” (by Roman Latkovic and Robert LaQuay, Ph.D) which takes a thorough look at this issue- you can see the same research at their blog. Basically, when you start to break down individual clicks by IP and user agent, it becomes clear many bots are indeed inflating bit.ly tracking.

Javascript Disabled

Second, there’s javascript. The majority of Adobe implementations these days rely on the user firing JavaScript (some older implementations or mobile implementations may fire a hard-coded beacon, but this is increasingly rare). Link shorteners, however, run WITHOUT javascript- meaning devices that have javascript disabled would count in bit.ly but NOT in Adobe.

Lost Referrer Information

Third, bit.ly (or twitter traffic in general) may cause you to lose referrer information. Someone coming from a twitter app rather than a webpage won’t have a referrer-it may look like “Direct Traffic”. Query string parameters SHOULD always carry through, though, so make sure your shortened links include tracking codes.

Conclusion

With this information in mind, I’d be more surprised to see bit.ly numbers that MATCH an Analytics tool than I am to see wide discrepancies. What’s your experience, and what are your theories behind them?