123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- require 'mixpanel_client'
- require 'date'
- module Agents
- class MixpanelAgent < Agent
- include WebRequestConcern
- cannot_receive_events!
- can_dry_run!
- default_schedule "every_1d"
- DEFAULT_EVENTS_ORDER = [['{{date_published}}', 'time'], ['{{last_updated}}', 'time']]
- description do
- <<-MD
- The Mixpanel Agent checks for analytics data and returns an event.
-
-
- In this Agent, the default value for `events_order` is `#{DEFAULT_EVENTS_ORDER.to_json}`.
- MD
- end
- def default_options
- {
- 'event_name' => "Page Visit",
- 'property' => "Page",
- 'value' => "home",
- 'time' => 24,
- 'interval' => 'hour'
- }
- end
- event_description <<-MD
- Events look like:
- {
- "count": "45",
- 'event_name': "Page Visit",
- 'property': "Page",
- 'value': "home",
- 'time': 24,
- 'interval': 'hour'
- }
- MD
- def working?
- end
- def validate_options
- errors.add(:base, "event_name is required") unless options['event_name'].present?
- unless options['property'].present? && options['value'].present?
- errors.add(:base, "Please provide 'property' and 'value'")
- end
- validate_web_request_options!
- validate_events_order
- end
- def events_order
- super.presence || DEFAULT_EVENTS_ORDER
- end
- def check
- create_event :payload => {
- count: mixpanel_event_number(options),
- event_name: options['event_name'],
- property: options['property'],
- value: options['value'],
- time: options['time'],
- interval: options['interval']
- }
- end
- protected
- def mixpanel_config
- {
- api_key: ENV['MIXPANEL_API_KEY'],
- api_secret: ENV['MIXPANEL_SECRET_KEY']
- }
- end
- def mixpanel_client
- @mixpanel_client ||= Mixpanel::Client.new(mixpanel_config())
- end
- def mixpanel_event_number(options)
- property, value = options[:property], options[:value]
- unless (property && value) || (!property && !value)
- raise "Must specify both 'property' and 'value' or none"
- end
- if [TrueClass, FalseClass].include?(value.class)
- raise "As of Aug 7, 2013, MixPanel has a bug with querying boolean values\nPlease use number_for_event_using_export until that's fixed"
- end
- event_name = options[:event_name]
- unless event_name
- raise "Event name must be provided"
- end
- type = options[:type] || "general"
- unless ["unique", "general", "average"].include? type
- raise "Invalid type #{type}"
- end
- num_days = options[:time] || 24
- interval = options[:interval] || "hour"
- mixpanel_options = {
- type: type,
- unit: interval,
- interval: num_days,
- limit: 5,
- }
- if property && value
- mixpanel_endpoint = "events/properties/"
- mixpanel_options.merge!({
- event: event_name,
- values: [value],
- name: property
- })
- else
- mixpanel_endpoint = "events/"
- mixpanel_options.merge!({
- event: [event_name]
- })
- end
- data = mixpanel_client.request(mixpanel_endpoint, mixpanel_options)
- total_for_events(data)
- end
- def total_for_events(data)
- counts_per_property = data["data"]["values"].collect do |c, values|
- values.collect { |k, v| v }.inject(:+)
- end
-
- counts_per_property.inject(:+)
- end
-
- def number_for_event_using_export(event_name, property, value, num_days = 30)
-
-
-
-
- to_date = Date.today
- from_date = to_date - num_days
- data = mixpanel_client.request('export', {
- event: [event_name],
- from_date: from_date.to_s,
- to_date: to_date.to_s,
- where: "boolean(properties[\"#{property}\"]) == #{value} ",
- })
- data.count
- end
- end
- end
|