lauripiispanen/auto-gtm-form-abandonment

Using Input Label instead of ID and targeting other fields

Creativenauts opened this issue · 0 comments

Thought I would share since I recently implemented this on one of my projects. Below is the code I'm using in order to use form class attribute and input labels. I also extended the event tracking to listen for other fields such as select and textarea.

Ended up using jquery because I absolutely suck at pure javascript. So you will be required to have it loaded on your site if you go my route. Perhaps someone can show a pure javascript solution :)

Enjoy!

(function($) {
  if (typeof document.querySelectorAll === "undefined") {
    return
  }
    window.addEventListener('beforeunload', function(e) {
      findUnsubmittedForms().forEach(function(it) {
        window.dataLayer.push({
          'event' : 'formAbandonment',
          'eventCategory' : 'Form Abandonment',
          'eventAction' : it.name + ": " + it.history.join(" > ")
        })
      })
    })

    var history = {}

    window.addEventListener("load", function() {
      document.addEventListener("change", function(e) {
        var target = e.target
        if (target && target.tagName && (target.tagName.toUpperCase() == "INPUT" || "SELECT" || "TEXTAREA")) {
          var inputName = $(event.target).parent().parent().find('label').text()
          var form = target.form
          if (form && inputName) {
            var formName = form.getAttribute("class")
            if (typeof history[formName] == "undefined") {
              history[formName] = []
            }
            if (history[formName].slice(-1) != inputName) {
              history[formName].push(inputName)
            }
          }
        }
      })
    })

    function findUnsubmittedForms() {
      return Object.keys(history).filter(hasNoFormSubmitEvent(window.dataLayer)).map(findFormFromHistory).filter(notEmpty)
    }

    function hasNoFormSubmitEvent(dataLayer) {
      return function(name) {
        return dataLayer.filter(isFormSubmitEvent).map(getFormName).indexOf(name) == -1
      }
    }

    function isFormSubmitEvent(e) {
      return e.event === 'gtm.formSubmit'
    }

    function getFormName(e) {
      return e['gtm.element'].class
    }

    function findFormFromHistory(name) {
      return {
        name: name,
        history: (history[name] || [])
      }
    }

    function notEmpty(form) {
      return form.history.length > 0
    }

})(jQuery)