CampaignCollector is a small utility library that allows you to easily collect campaign parameters (utm_
+) from a URL and store/persist them in browser storage. This is useful for integrating campaign data with lead generation forms and CRMs.
Important
This library does not send data to any analytics platform or 3rd party service. It is up to the implementor to decide how it is used.
Features
- Natively supports all 9 standard campaign parameters (e.g.
utm_*
). - Supports storage of 17 custom parameters with a defined prefix/namespace.
- Ability to define field mappings for each parameter to attach data to form submissions.
- Define 1st party cookies and global variables to capture and map along side your in-url campaign parameters.
Note
This library is a port/rewrite of Attributor.js.
CampaignCollector offers more flexibility with its API than Attributor.js, and has been re-written with a modern Javascript footprint, and mulitple deployment/implementation options.
For Google Tag Manager users - this is the preferred and easiest deployment method.
Install the Campaign Collector tag template in the community gallery. You can view the tag template repository here.
In the event you need to have more control over the logic of when the library is loaded - you can use the following async loader to mount an instance.
This most often will apply to users using a different TMS like Adobe Launch, or those who are not using a TMS at all.
(function(l,o,a,d,e,r){
e=o.createElement(a);e.onload=d;e.defer=1;
e.src="https://cdn.jsdelivr.net/gh/levelinteractive/campaign-collector@latest/dist/core.min.js";
r=o.getElementsByTagName(a)[0];r.parentNode.insertBefore(e,r);
})(window, document, 'script', function() {
// Initialize an instance
window._CampaignData = new CampaignCollector();
});
If you are using a build process and want to include the library as a dependency - you can install it via NPM.
Install the Package
$ npm install campaign-collector
Import the Package
import CampaignCollector from 'campaign-collector';
// Initialize an instance
window._CampaignData = new CampaignCollector();
Google has defined a set of standard UTM parameters that are widely supported across advertising/martech platforms. These parameters are natively supported by the library.
utm_source
utm_medium
utm_campaign
utm_term
utm_content
utm_id
utm_marketing_tactic
utm_creative_format
utm_source_platform
In addition to the standard parameters - this library offers flexibility for a set list of custom parameters. By default, the library will look for any parameter that starts with specific namespace (lvl
by default). The namespace/prefix can be customized by setting the namespace
config option to a different value. These parameters align closely with major advertising platform URL macros (e.g. Google Ads "ValueTrack" and similar).
lvl_platform
lvl_source
lvl_campaign_name
lvl_campaign
lvl_group
lvl_ad
lvl_creative
lvl_feed
lvl_product
lvl_extension
lvl_geo_int
lvl_geo_phy
lvl_device
lvl_matchtype
lvl_placement
lvl_network
lvl_target
Note
The custom parameters are not extendable at this time, we may offer that capability in future versions - but there are no current plans to do so.
The library uses a timeout-based session approach to store the "last" touch campaign data. This is similar to how Google Analytics functions (but not exact).
- An active session with explicit campaign data cannot be overwritten by referrer parsing.
- On a users first visit, the
first
andlast
touch data will be the same. - Sessions expire after 30 minutes of inactivity (unless customized via
sessionTimeout
in the config). "Inactivity" is defined as no page views, or generic click events on the page. - First touch data can/will be misleading for browsers that cap cookie expiration at 7 days (e.g. Safari). This can be mitigated (to an extent) by rewriting the
_lvl_cc_first
cookie via a 1st party service - but will require infrastructure not provided by this library.
Scenario A:
- A "first time visitor" enters the site on a page with
?utm_source=google&utm_medium=cpc&utm_campaign=helloworld
in the URL. - A new session is started, and the
first
andlast
touch data is set to the above parameters. - (10 Minutes Pass) The user opens a new tab in Google/Bing and searches your brand, then clicks on an organic result.
- A new session is NOT started -- because the active session has explicit campaign data. The existing session is extended an additional 30 minutes.
- (> 30 Minutes Pass) The user sees an organic social media post and clicks a link to your site.
- A new session IS started, and the
last
touch data is set to the explicit campaign data in the URL (if present) -OR- the referrer is parsed to implicitly set a source/medium.
The domain to set 1st party cookies on. If null
, the cookies will be set on the current root domain. If a string, the cookie will be set on the specified domain. Default: null
.
An array of hostnames to decorate with stored campaign data to support cross-domain persistence. When set, clicks on links will automatically be decorated. Default: []
.
When set to true
, the library will monkeyPatch the history.pushState
method to ensure that stored campaign data is hydrated to extend the session on SPA navigation. Default: false
.
An object that defines field mappings for each storage group and its individual parameters. This fieldMap object is used for filling data into form inputs, as well as defining what cookies
and globals
to pull into the stored campaign data when running the fill()
or grab()
methods.
There are 4 supported storage groups: first
, last
, cookies
, and globals
. The first
and last
groups store the campaign data from URL parameters. These two groups have utm
and $ns
objects inside them - $ns
being a reference to the defined namespace
config option.
By default, the library will automatically generate a fieldMap for the first
and last
storage groups using sensible defaults. last
will assume a field selector that exactly matches the parameter name (e.g. utm_source
) -- while first
will assume a field selector that matches the parameter name with a suffix of _1st
(e.g. utm_source_1st
).
A few important notes about the fieldMap
object:
- Custom fieldMap objects are merged with the default fieldMap object. This means you only need to configure the fields you want to override.
- The structure is
storageKey
:fieldSelector
pairs. WherefieldSelector
is a string that will be used to create a CSS selector using whatever means you defined in thefieldTargetMethod
configuration option.
Example fieldMap
Object:
{
"last": {
"utm": {
"source": "utm_source__c",
},
"$ns": {
"matchtype": "matchtype__c",
}
},
"cookies": {
"_fbp": "meta__fbp",
"_fbc": "meta__fbc",
},
"globals": {
"location.href": "conversion_url",
}
}
The above example defines a custom fieldMap
for to take the last touch utm_source
, and lvl_matchtype
and map it to a field with a name
attributes of utm_source__c
, and matchtype__c
. It instructs the library to grab the _fbp
and _fbc
cookies and map them to fields with name
attributes of meta__fbp
and meta__fbc
respectively. Lastly, the globals
object defines values to grab from the window
object and map to fields with a name
attribute of conversion_url
.
An array of strings that define the method used to target form fields. This allows for flexibility for form field markup variety. Valid values are: name
, class
, parentClass
, and dataAttribute
. Default: ['name']
.
Example Field Targeting Markup:
<!-- "name" -->
<input type="hidden" name="{{fieldSelector}}">
<!-- "class" -->
<input type="hidden" class="{{fieldSelector}}">
<!-- "parentClass" -->
<div class="{{fieldSelector}}">
<input type="hidden">
</div>
<!-- "dataAttribute" -->
<input type="hidden" data-campaign-collector="{{fieldSelector}}">
An object that defines filters to apply values for cookies
and globals
objects. This is useful for transforming data before it is filled into form fields. The object is structured as storageKey
: function
pairs. The function should accept a single argument (the value to be transformed) and return the transformed value.
Use .fill()
to manually set form field values from stored campaign data. Accepts an options
object with the following properties:
Use .grab()
to retrieve a JSON object of all stored campaign data. Accepts an options
object with the following properties:
without
(array) - An array of keys to exclude from the returned object. Allowed values:first
- Excludes standard UTM parameterslast
- Excludes custom parameterscookies
- Excludes 1st party cookiesglobals
- Excludes global variables
applyFilters
(boolean) - Iftrue
, will apply any defined filters to the returnedcookies
andglobals
objects. Default:false
.