snitchy

DataLayer push made easy

Usage no npm install needed!

<script type="module">
  import snitchy from 'https://cdn.skypack.dev/snitchy';
</script>

README

📈 Snitchy

stability-wip NPM version Coverage Status License

DataLayer push made easy

This module aims to reach 3 goals:

  1. One single source of truth aka one model for strutured data to be pushed
  2. Write once, use everywhere
  3. Use dynamic values as easily as possible

Getting started

  • Add snitchy-loader
  • Import snitchy
  • Import and load your data (.xlsx via loader or .js, .json)
  • Add kapla-snitchy (if you use Kapla)
  • Dispatch 'page' or 'component' (automatically or programmatically)

Usage

Pages

Pushing data from pages use the data-namespace attribute.
Data variables can be declared once for all pages into { pages/all/[layer(s)] }.
Custom variables should go into { pages/[namespace]/[layer(s)] } and will override globals.

Data pushed are { layer1: {}, … }.


snitchy.page([layer, values, scope])

layer

Type: string | array

values

Type: object

For use with $valSomething (see below).

scope

Type: thisArg

For use with $thisSomething where "this" will refers to "scope".

How to use it

Different scenarios:

  1. No framework (Vue.js), no page transition (Barba.js)
    • Into main.js, will be called on every page load
  2. With page transition (Barba.js)
    • Global, no view specific data
      • Into main.js, will be called on first page load
        snitchy.page(…);
        
      • AND intoviews/ViewManager.js, will be called on every page transition
        Barba.Dispatcher.on('transitionCompleted', currentStatus => {
          snitchy.page(…);
        });
        
    • By "view", with specific data
      • Into views/view.js, will be called on every transition complete
        onEnterCompleted() {
          snitchy.page(…, …, this.view);
        },
        
  3. With framework (Vue.js)
    • TBD (Same logic? Should be coupled globally with vue-router or by "root component"…)

Component

Pushing data from components are organised by slug and description.
By default, all the descriptions are pushed.
You can use a special 'trigger' property (with kapla-snitchy) to push automatically "onTriggerValue".
In this case only this content will be pushed (trigger property will be removed before).

Data pushed are contents of slug/description(s).


snitchy.component([slug, values, scope, trigger])

slug

Type: string

"Name" of the component.

values

Type: object

For use with $valSomething (see below).

scope

Type: thisArg

For use with $thisSomething where "this" will refers to "scope".

trigger (kapla-snitchy only)

Type: string

Filter descriptions with some "trigger".

How to use it

// When/where you want to push…
snitchy.component('slug', …);

Manual

snitchy.push(data)

data

Type: object

"Raw" object for dataLayer.push().


Properties

snitchy.debug

Type: boolean
Default: false

Do not push to dataLayer, display into console.

snitchy.variables

Type: object

Your loaded data, KPIs or wathever…

snitchy.prefixes

Type: object

Available prefixes (see below).


Prefixes

You can use "static" values or "dynamic" ones. Dynamic values start with a $ (static vs $dynamic).

When working with dynamic values, you need to use $camelCaseNotation. First "part" refers to prefix. Some are evaluated automatically, some should be passed through values or scope (see above).

You can add you own prefixes with addPrefix().

  • $url: window.location.href
  • $tagName: where "name" is the name of the tag.
    Examples:
    • $tagTitle refers to <title /> content.
  • $attrName: where "name" is the name of the attribute.
    Examples:
    • $attrLang refers to lang="" value (first found, <html lang="">)
    • $attrDataSomething refers to data-something="" value
  • $valName: where "name" is the key of the "values" parameter (see above).
    Examples:
    • $valProductId refers to { productId: 666 }
  • $thisProp: where "prop" is the property of the instance triggering the push.
    Should be used with the "scope" parameter (see above).
    Examples:
    • $thisCategory refers to this.category. this should be passed as the "scope" argument
  • $el… (kapla-snitchy only) Examples:
    • $elTextContent returns this.$el.textContent
    • $elAttribute returns this.$el.getAttribute('attribute')
  • $ref… (kapla-snitchy only) Examples:
    • $refKeywordTextContent returns this.$refs[keyword].textContent
    • $refKeywordAttribute returns this.$refs[keyword].getAttribute('attribute')

Data (variables) example

{
  "pages": {
    "all": {
      "page": {
        "title": "$tagTitle",
        "language": "$attrLang"
      },
    },
    "products": {
      "page": {
        "category": "$valCategory"
      }
    },
    "singleProduct": {
      "page": {
        "id": "thisProductId"
      }
    }
  },
  "component": {
    "search": {
      "default": {
        "trigger": "submit",
        "event": "search",
        "eventAction": "submit",
        "eventCategory": "form",
        "eventRef": "$elAction",
        "eventValue": "$refsInputValue"
      }
    },
    "contact": {
      "success": {
        "trigger": "success",
        "event": "formSubmit",
        "eventAction": "submit",
        "eventCategory": "form",
        "eventValue": "$refInputValue"
      },
      "error": {
        "trigger": "error",
        "event": "formError",
        "eventAction": "submit",
        "eventCategory": "form",
        "eventValue": "$refInputValue"
      }
    },
    "social": {
      "event": "social",
      "eventAction": "$elDataAction",
      "eventValue": "elHref"
    }
  }
}

Usage

  • All pages: nothing
  • Products: snitchy.page('page', { category: 'shoes' })
  • Single product: snitchy.page('page', null, this.single) (instance)
  • Search component: nothing
  • Contact component: snitchy.component('contact', null, null, 'success') (or via kapla: $trigger('success')). Same for error…
  • Social component: snitchy.component('social') (or nothing with "trigger": "click")

Just for comparison, without this module:

dataLayer.push({
  page: {
    title: document.documentElement.querySelector('title').textContent,
    language: document.documentElement.lang,
  }
});

or

dataLayer.push({
  trigger: 'error'
  event: 'formError'
  eventAction: 'submit'
  eventCategory: 'form'
  eventValue: document.querySelector('[name="…"]'),
});

Feel free to comment , add an issue or submit a pull request…