diff --git a/lib/customerio/client.rb b/lib/customerio/client.rb index ffb8754..61cf8a9 100644 --- a/lib/customerio/client.rb +++ b/lib/customerio/client.rb @@ -44,6 +44,14 @@ def unsuppress(customer_id) @client.request_and_verify_response(:post, unsuppress_path(customer_id)) end + def unique_track(event_id, customer_id, event_name, attributes = {}) + raise ParamError.new("event_id must be a valid ULID") if !valid_ulid?(event_id) + raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id) + raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name) + + create_customer_event(customer_id, event_name, attributes, event_id) + end + def track(customer_id, event_name, attributes = {}) raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id) raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name) @@ -157,10 +165,11 @@ def create_or_update(attributes = {}) @client.request_and_verify_response(:put, url, attributes) end - def create_customer_event(customer_id, event_name, attributes = {}) + def create_customer_event(customer_id, event_name, attributes = {}, event_id = nil) create_event( url: "#{customer_path(customer_id)}/events", event_name: event_name, + event_id: event_id, attributes: attributes ) end @@ -183,11 +192,12 @@ def create_pageview_event(customer_id, page, attributes = {}) ) end - def create_event(url:, event_name:, anonymous_id: nil, event_type: nil, attributes: {}) + def create_event(url:, event_name:, anonymous_id: nil, event_type: nil, event_id: nil, attributes: {}) body = { :name => event_name, :data => attributes } body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp]) body[:anonymous_id] = anonymous_id unless is_empty?(anonymous_id) body[:type] = event_type unless is_empty?(event_type) + body[:id] = event_id unless is_empty?(event_id) @client.request_and_verify_response(:post, url, body) end @@ -196,6 +206,10 @@ def valid_timestamp?(timestamp) timestamp && timestamp.is_a?(Integer) && timestamp > 999999999 && timestamp < 100000000000 end + def valid_ulid?(ulid) + !!(ulid =~ /\A[0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz]{26}\z/) + end + def is_empty?(val) val.nil? || (val.is_a?(String) && val.strip == "") end diff --git a/spec/client_spec.rb b/spec/client_spec.rb index dfd9321..f42815e 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -392,6 +392,25 @@ def json(data) client.track(5, "purchase", type: "socks", price: "13.99", timestamp: "Hello world") end + context "tracking a unique event" do + let(:event_id) { "01HB4HBDKTFWYZCK01DMRSWRFD" } + + it "throws an error when event_id is invalid ulid" do + stub_request(:put, /track.customer.io/) + .to_return(status: 200, body: "", headers: {}) + + lambda { client.unique_track(" ", 1, "test_event") }.should raise_error(Customerio::Client::ParamError, "event_id must be a valid ULID") + end + + it "sends a POST request to the customer.io's anonymous event API" do + stub_request(:post, api_uri("/api/v1/customers/5/events/#{event_id}")). + with(body: { name: "purchase", data: {} }). + to_return(status: 200, body: "", headers: {}) + + client.unique_track(event_id, 5, "purchase") + end + end + context "tracking an anonymous event" do let(:anon_id) { "anon-id" }