Module: MetaEvents::Helpers

Defined in:
lib/meta_events/helpers.rb

Overview

This module gets included as a Rails helper module, if Rails is available. It defines methods that are usable by views to do tracking from the front-end – both auto-tracking and frontend events.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.meta_events_javascript_tracking_prefix(prefix = nil) ⇒ Object

Defines (or returns) the prefix we use for our class and data attributes; this just needs to be unique enough that we are highly unlikely to collide with any other attributes.


10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/meta_events/helpers.rb', line 10

def meta_events_javascript_tracking_prefix(prefix = nil)
  if prefix == nil
    @_meta_events_javascript_tracking_prefix
  else
    if (prefix.kind_of?(String) || prefix.kind_of?(Symbol)) && prefix.to_s.strip.length > 0
      @_meta_events_javascript_tracking_prefix = prefix.to_s.strip
      @_meta_events_javascript_tracking_prefix = $1 if @_meta_events_javascript_tracking_prefix =~ /^([^_]+)_+$/i
    else
      raise ArgumentError, "Must supply a String or Symbol, not: #{prefix.inspect}"
    end
  end
end

Instance Method Details

#meta_events_frontend_events_javascriptObject

Returns a JavaScript string that, when placed on a page into which meta_events.js.erb has been included, sets up all defined front-end events so that they can be fired by that JavaScript.


112
113
114
115
116
117
118
# File 'lib/meta_events/helpers.rb', line 112

def meta_events_frontend_events_javascript
  out = ""
  (meta_events_defined_frontend_events || { }).each do |name, properties|
    out << "MetaEvents.registerFrontendEvent(#{name.to_json}, #{properties.to_json});\n"
  end
  out.html_safe
end

#meta_events_prefix_attribute(name) ⇒ Object

PRIVATE (though there's no point to declaring something private in a helper; everything's being called from the same object anyway). Simply prepends our prefix, plus an underscore, to whatever's passed in.


29
30
31
# File 'lib/meta_events/helpers.rb', line 29

def meta_events_prefix_attribute(name)
  "#{MetaEvents::Helpers.meta_events_javascript_tracking_prefix}_#{name}"
end

This works exactly like Rails' built-in link_to method, except that it takes a :meta_event property in html_options and turns the link into a tracked link, using #meta_events_tracking_attributes_for, above.

The :meta_event property is actually required; this is because, presumably, you're calling this method exactly because you want to track something, and if you didn't pass :meta_event, you probably misspelled or forgot about it.

Obviously, feel free to create a shorter alias for this method in your application; we give it a long, unique name here so that we don't accidentally collide with another helper method in your project.


95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/meta_events/helpers.rb', line 95

def meta_events_tracked_link_to(name = nil, options = nil, html_options = nil, &block)
  html_options, options, name = options, name, nil if block_given?

  unless html_options && html_options[:meta_event]
    raise ArgumentError, "You asked for a tracked link, but you didn't provide a :meta_event: #{html_options.inspect}"
  end

  if block_given?
    link_to(options, meta_events_tracking_attributes_for(html_options, meta_events_tracker), &block)
  else
    link_to(name, options, meta_events_tracking_attributes_for(html_options, meta_events_tracker))
  end
end

#meta_events_tracking_attributes_for(input_attributes, event_tracker = meta_events_tracker) ⇒ Object

Given a Hash of attributes for an element – and, optionally, a MetaEvents::Tracker instance to use; we default to using the one exposed by the meta_events_tracker method – extracts a :meta_event property, if present, and turns it into exactly the attributes that meta_events.js.erb can use to detect that this is an element we want to track (and thus correctly return it from its forAllTrackableElements method). If no :meta_event key is present on the incoming set of attributes, simply returns exactly its input.

The :meta_event property must be a Hash, containing:

:category

The name of the category of the event;

:event

The name of the event within the category;

:properties

Any additional properties to fire with the event; this is optional.


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/meta_events/helpers.rb', line 44

def meta_events_tracking_attributes_for(input_attributes, event_tracker = meta_events_tracker)
  # See if we've even got an event...
  return input_attributes unless input_attributes && (input_attributes[:meta_event] || input_attributes['meta_event'])

  # If so, let's start populating our set of output attributes.
  # #with_indifferent_access dups the Hash even if it already has indifferent access, which is important here
  output_attributes = input_attributes.with_indifferent_access
  event_data = output_attributes.delete(:meta_event)

  # A little error-checking...
  unless event_data.kind_of?(Hash)
    raise ArgumentError, ":meta_event must be a Hash, not: #{event_data.inspect}"
  end

  event_data.assert_valid_keys(%w{category event properties})

  # Grab our event data...
  category = event_data[:category]
  event = event_data[:event]
  properties = event_data[:properties] || { }

  unless category && event
    raise ArgumentError, "You must supply :category and :event in your :meta_event attributes, not: #{event_data.inspect}"
  end

  # Ask the Tracker to compute the set of properties we should be firing with this event...
  props_data = event_tracker.effective_properties(category, event, properties)

  # Add our class to the +:class+ attribute -- Rails supports declaring +:class+ as an Array, and so we'll use
  # that here. It works fine even if +:class+ is a string of space-separated class names.
  classes = Array(output_attributes.delete(:class) || [ ])
  classes << meta_events_prefix_attribute("trk")
  output_attributes[:class] = classes

  # Set the data attributes we'll be looking for...
  output_attributes["data-#{meta_events_prefix_attribute('evt')}"] = props_data[:external_name]
  output_attributes["data-#{meta_events_prefix_attribute('prp')}"] = props_data[:properties].to_json

  # And we're done!
  output_attributes
end