class OEHClient::Interaction::Interaction # constants used to construct the restful API Request URL API_REALTIME = "/interaction" API_OFFLINE = "/offline" # ONE attributes that are either in the request and/or returned in the response ONE_PARAM_URI = "uri" ONE_PARAM_CK = "customerKey" ONE_PARAM_TID = "tid" ONE_PARAM_SESSION = "session" ONE_PARAM_SK = "sk" ONE_PARAM_TS = "timestamp" ONE_PARAM_PROPERTIES = "properties" # Property Hash Keys ONE_PROPERTIES_NAME = "name" ONE_PROPERTIES_VALUE = "value" # Collection objects returned in the response ONE_RESPONSE_OPTIMIZATIONS = "optimizations" ONE_RESPONSE_TRACKERS = "trackers" ONE_RESPONSE_CAPTURES = "captures" attr_accessor :uri, # The full touchpoint/interaction URI used to post the interaction :space, # The configured OEHClient::Config::Space object that represents the :timestamp, # A millisecond value representing a Time value of the interaction :customer_key, # The customer to which this interaction is related :tid, # The Thunderhead ID (TID) to which this interaction is related :session, # The session id to which this interaction is related :optimizations, # The collection of optimizations that are relevent for the interaction :trackers, # The collection of tracking point data that are relevant for the interaction :captures, # The collection of capture point data that are relevant for the interactions :errors ### ### ------------- Class Methods ### class << self # post def post(site_key, uri, timestamp=nil, tid=nil, customer_key=nil, properties={}) # setup the baseline attributes hash with the site_key and interaction URI, which are the # minimal values needed for an interaction attributes = { :sk => site_key, :uri => uri } # conditionally merge the rest of the attributes if they are passed attributes.merge!(:timestamp => timestamp) if (!timestamp.nil? && !timestamp.empty?) attributes.merge!(:tid => tid) if (!tid.nil? && !tid.empty?) attributes.merge!(:ck => customer_key) if (!customer_key.nil? && !customer_key.empty?) # create a new interaction using all attributes pass new_interaction = OEHClient::Interaction::Interaction.new(attributes) # Send the interaction for processing and return the instance of the interaction class new_interaction.send(properties) end # class-level wrapper to create a new instance of the OEHClient::Interaction::Interaction class, call the # send_update method, and return the resulting instance of the same class def update(site_key, uri, properties={}, tid=nil, customer_key=nil) # setup the baseline attributes hash with the site_key and interaction URI, which are the # minimal values needed for an interaction attributes = { :sk => site_key, :uri => uri } # conditionally merge the rest of the attributes if they are passed attributes.merge!(:tid => tid) if (!tid.nil? && !tid.empty?) attributes.merge!(:ck => customer_key) if (!customer_key.nil? && !customer_key.empty?) # create a new interaction using all parameters pass new_interaction = OEHClient::Interaction::Interaction.new(attributes) # send the update and return the current object new_interaction.send_update(properties) end end ### ### ------------- Instance Methods ### def initialize(attributes=nil) # set the instance attributes is the parameter hash is created if (!attributes.nil? && attributes.kind_of?(Hash)) @uri = attributes[:uri] if (attributes.has_key?(:uri)) @customer_key = attributes[:ck] if (attributes.has_key?(:ck)) @tid = attributes[:tid] if (attributes.has_key?(:tid)) @session = attributes[:session] if (attributes.has_key?(:session)) @timestamp = attributes[:timestamp] if (attributes.has_key?(:timestamp)) @space = OEHClient::Config::SpaceManager.instance.get(attributes[:sk]) if (attributes.has_key?(:sk)) end end # send() will post a new interaction using either the realtime (current timestamp) or the offline (historic) # API interface based on the existence of a timestamp value def send(parameters={}) # call the appropriate method based on the existance of the timestamp value ((minimal_parameters? && !@timestamp.nil? && @timestamp > 0) ? send_offline(@space.token) : send_realtime(@space.token, parameters)) # return the current instance interacton self end # send_new posts a new interaction using the existing instance data, but for a different touchpoint # URI. The method returns a new instance of the OEHClient::Interaction::Interaction class def send_new(uri, timestamp=nil, parameters={}) # protect against NIL by creating a new Hash object if the parameters, for any reason is # NIL parameters ||= Hash.new # create a new interaction using all parameters from the existing other than the new touchpoint # URI and timestamp of the current Interaction instance. The method can be used to submit new # requests for the same customer, tid, & session new_interaction = OHEClient::Interaction::Interaction.new({ :uri => uri, :ck => @customer_key, :tid => @tid, :session => @session, :sk => @space.site_key, :timestamp => timestamp }) # Send the interaction for processing and return the current instance new_interaction.send(parameters) end # send_update allows the system to update the capture and tracking properties that are defined as # part of the existing interaction def send_update(properties={}) # force the properties object to be an empty Hash if, for any reason, it is NIL properties ||= Hash.new # Call the PUT method to update the OEHClient::Helper::Response.handle(OEHClient.put(@space.token(), OEHClient::Helper::Request.format_url(realtime_url, {:sk => @space.site_key}), nil, request_data(properties))) unless properties.empty? # return the current object self end private # send_realtime posts a new interaction occuring at the moment (in realtime). The response attributes # are mapped to the current instance attributes for all valid requests def send_realtime(token, parameters={}) response = OEHClient::Helper::Response.handle(OEHClient.post(token, OEHClient::Helper::Request.format_url(realtime_url, {:sk => @space.site_key}), nil, request_data(parameters)) ) map_response(response) end # send_offline posts a historic interaction, using a specified timestamp def send_offline(token) response = OHEClient::Helper::Response.handle(OEHClient.put(token, OEHClient::Helper::Request.format_url(offline_url, {:sk => @space.site_key}), nil, request_data)) map_response(response) end # map_response takes the attributes returned in an interaction response and maps it to exiting # attributes in the current instance of the interaction object def map_response(response) # Save the tid and session data if they where not previously used in the request @tid = response[ONE_PARAM_TID] if (@tid.nil? || (!@tid.blank? && @tid != response[ONE_PARAM_TID])) @session = response[ONE_PARAM_SESSION] if @session.nil? # capture the optimizations returned from the request and map it to the OEHClient::Interaction::Optimization # class # initialize the optimizations collection if it is null @optimizations ||= Array.new # map each of the optimizations to the OEHClient::Interaction::Optmization class response[ONE_RESPONSE_OPTIMIZATIONS].each do | response_optimization | @optimizations << OEHClient::Interaction::Optimization.create(response_optimization) end # capture the trackers returned from the request and mpt it to the OEHClient::Interaction::Tracker # class # TODO: Create OEHClient::Interaction::Tracker class @trackers = response[ONE_RESPONSE_TRACKERS] # capture the capture points returned from the request and map it to the OEHClient::Interaction::Capture # class # TODO: Create OEHClient::Interaction::Capture class @captures = response[ONE_RESPONSE_CAPTURES] end # minimal_parameters? determines if the minimal number of request parameters (uri & site_key) are # present in the current instance of the interaction class. This is a helper method that is used # before making any request def minimal_parameters?() !@uri.nil? && !@site_key.nil? end # request_url returns the base of the request URL used to make either a realtime or offline request # through published API def request_url() "#{OEHClient::Helper::Request::ONE_PROTOCOL}#{@space.host}#{OEHClient::Helper::Request::THUNDERHEAD_DOMAIN}#{OEHClient::Helper::Request::ONE_URI_PART}#{OEHClient::Helper::Request::API_URI_PART}#{OEHClient::Helper::Request::API_VERSION}" end # realtime_url is the interaction part of the API URI def realtime_url() "#{request_url}#{API_REALTIME}" end # offline_url appends the /offiline URI part to add support for historic data loading of interactions def offline_url() "#{realtime_url}#{API_OFFLINE}" end # request_data creates a properly formatted Hash object that represents the body of the request needed # for POST and PUT operations def request_data(passed_properties={}) # protect agains a NIL value in the passed_properties Hash passed_properties ||= Hash.new # Initialize the parameters hash parameters ||= Hash.new # merge in the different parts of the request data if the values currently exist within # the instance of the class parameters.merge!({ONE_PARAM_URI => @uri}) if (!@uri.nil? && @uri.length > 0) parameters.merge!({ONE_PARAM_CK => @customer_key}) if (!@customer_key.nil? && @customer_key.length > 0) parameters.merge!({ONE_PARAM_TID => @tid}) if (!@tid.nil? && @tid.length > 0) parameters.merge!({ONE_PARAM_SESSION => @session}) if (!@session.nil? && @session.length > 0) parameters.merge!({ONE_PARAM_TS => @timestamp}) if (!@timestamp.nil?) # for each of the properties hash entry, build a name/value pair in the properties collection properties = Array.new passed_properties.each do | key, value | properties << {ONE_PROPERTIES_NAME => key.to_s, ONE_PROPERTIES_VALUE => value} end # merge the properties (name / value) connections if there are additonal values to pass parameters.merge!({ONE_PARAM_PROPERTIES => properties}) if (properties.length > 0) # return the full parameter hash return(parameters) end end