Skip to content

Instantly share code, notes, and snippets.

@nathan-appere
Last active February 2, 2022 16:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathan-appere/c3e842e6d68e99593e0e1770b176bf5c to your computer and use it in GitHub Desktop.
Save nathan-appere/c3e842e6d68e99593e0e1770b176bf5c to your computer and use it in GitHub Desktop.
Quick segment wrapper for Rails
# Wrapper for Segment.
module Services::Analytics
PREVENT_EXCEPTION = true
def self.backend_default
key = ENV['SEGMENT_SOURCE_SERVER_KEY']
if Rails.env.production? || (key && !key.blank?)
@backend_default ||= Segment::Analytics.new(
write_key: key,
)
else
@backend_default ||= Segment::Analytics.new(
write_key: 'test',
stub: true,
)
end
end
# References:
# - https://segment.com/docs/connections/sources/catalog/libraries/server/ruby/#track
def self.track_event(user:, event_name:, properties: {}, context: {}, request_rails: nil, source: :website, backend: self.backend_default)
return if !backend
user_id = user.try(:id) || 'anonymous'
properties ||= {}
context ||= {}
properties[:source] = :website
if request_rails
context = request_to_context(request_rails: request_rails, context: context)
end
track_identify(user: user)
payload = {
user_id: user_id,
event: event_name,
properties: properties,
context: context,
}
backend.track payload
[:ok]
rescue StandardError => e
if PREVENT_EXCEPTION
Raven.capture_exception(e)
[:error]
else
raise e
end
end
# References:
# - https://segment.com/docs/connections/sources/catalog/libraries/server/ruby/#page
def self.track_page(user:, properties: {}, context: {}, request_rails: nil, source: :website, backend: self.backend_default)
return if !backend
user_id = user.try(:id) || 'anonymous'
properties ||= {}
context ||= {}
properties[:source] ||= :website
if request_rails
context = request_to_context(request_rails: request_rails, context: context)
properties = request_to_properties(request_rails: request_rails, properties: properties)
end
track_identify(user: user)
payload = {
user_id: user_id,
properties: properties,
context: context,
}
backend.page payload
[:ok]
rescue StandardError => e
if PREVENT_EXCEPTION
Raven.capture_exception(e)
[:error]
else
raise e
end
end
def self.request_to_context(request_rails:, context:)
request_context = {
ip: request_rails.ip,
userAgent: request_rails.user_agent,
}
request_context.each { |k, v| context[k] = v if !context[k] }
context
end
def self.request_to_properties(request_rails:, properties:)
request_properties = {
controller: request_rails.params['controller'],
action: request_rails.params['action'],
referrer: request_rails.referrer,
path: request_rails.path,
url: request_rails.url,
}
request_properties.each { |k, v| properties[k] = v if !properties[k] }
properties
end
# References:
# - https://segment.com/docs/connections/sources/catalog/libraries/server/ruby/#identify
# - https://segment.com/docs/connections/spec/identify/#traits
def self.track_identify(user: nil, traits: {}, backend: self.backend_default)
return if !backend
user_id = user.try(:id) || 'anonymous'
traits ||= {}
if user
traits.merge!(
id: user.id,
username: user.username,
email: user.email,
createdAt: user.created_at,
admin: user.admin,
)
end
backend.identify(
user_id: user_id,
traits: traits,
)
[:ok]
rescue StandardError => e
if PREVENT_EXCEPTION
Raven.capture_exception(e)
[:error]
else
raise e
end
end
end
class ApplicationController < ActionController::Base
before_action :analytics_track_page
protected
def analytics_track_page
Services::Analytics.track_page(
user: current_user,
request_rails: request,
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment