customerio 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,16 @@
1
+ ## Customerio 0.5.0 - Apr 8, 2013 ##
2
+
3
+ * Removed deprecated methods around using a customer object. All calls simply take a hash of attributes now.
4
+ * Added ability to set a timestamp on a tracked event. Useful for backfilling past events.
5
+
6
+ ## Customerio 0.4.1 - Feb 18, 2013 ##
7
+
8
+ * Bug fixes related to the 4.0 change.
9
+
10
+ ## Customerio 0.4.0 - Feb 18, 2013 ##
11
+
12
+ * Added support for deleting customers.
13
+
1
14
  ## Customerio 0.3.0 - Dec 28, 2012 ##
2
15
 
3
16
  * Now raise an error if an API call doesn't respond with a 200 response code
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- customerio (0.4.0)
4
+ customerio (0.5.0)
5
5
  httparty (>= 0.5, < 1.0)
6
6
 
7
7
  GEM
@@ -12,7 +12,7 @@ GEM
12
12
  httparty (0.10.2)
13
13
  multi_json (~> 1.0)
14
14
  multi_xml (>= 0.5.2)
15
- multi_json (1.6.1)
15
+ multi_json (1.7.0)
16
16
  multi_xml (0.5.3)
17
17
  rake (0.9.2.2)
18
18
  rspec (2.8.0)
@@ -3,36 +3,16 @@ require 'httparty'
3
3
  module Customerio
4
4
  class Client
5
5
  include HTTParty
6
- base_uri 'https://app.customer.io'
7
-
8
- CustomerProxy = Struct.new("Customer", :id)
6
+ base_uri 'https://track.customer.io'
9
7
 
10
8
  class MissingIdAttributeError < RuntimeError; end
11
9
  class InvalidResponse < RuntimeError; end
12
10
 
13
- @@id_block = nil
14
-
15
- def self.id(&block)
16
- warn "[DEPRECATION] Customerio::Client.id customization is deprecated."
17
- @@id_block = block
18
- end
19
-
20
- def self.default_config
21
- @@id_block = nil
22
- end
23
-
24
11
  def initialize(site_id, secret_key)
25
12
  @auth = { :username => site_id, :password => secret_key }
26
13
  end
27
14
 
28
- def identify(*args)
29
- attributes = extract_attributes(args)
30
-
31
- if args.any?
32
- customer = args.first
33
- attributes = attributes_from(customer).merge(attributes)
34
- end
35
-
15
+ def identify(attributes)
36
16
  create_or_update(attributes)
37
17
  end
38
18
 
@@ -48,12 +28,11 @@ module Customerio
48
28
  event_name = args.first
49
29
  create_anonymous_event(event_name, attributes)
50
30
  else
51
- # Passed in a customer and an event name.
31
+ # Passed in a customer id and an event name.
52
32
  # Track the event for the given customer
53
- customer, event_name = args
33
+ customer_id, event_name = args
54
34
 
55
- identify(attributes_from(customer))
56
- create_customer_event(id_from(customer), event_name, attributes)
35
+ create_customer_event(customer_id, event_name, attributes)
57
36
  end
58
37
  end
59
38
 
@@ -63,7 +42,6 @@ module Customerio
63
42
  raise MissingIdAttributeError.new("Must provide a customer id") unless attributes[:id]
64
43
 
65
44
  url = customer_path(attributes[:id])
66
- attributes[:id] = custom_id(attributes[:id])
67
45
 
68
46
  verify_response(self.class.put(url, options.merge(:body => attributes)))
69
47
  end
@@ -78,13 +56,19 @@ module Customerio
78
56
 
79
57
  def create_event(url, event_name, attributes = {})
80
58
  body = { :name => event_name, :data => attributes }
59
+ body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
81
60
  verify_response(self.class.post(url, options.merge(:body => body)))
82
61
  end
83
62
 
84
63
  def customer_path(id)
85
- "/api/v1/customers/#{custom_id(id)}"
64
+ "/api/v1/customers/#{id}"
86
65
  end
87
66
 
67
+ def valid_timestamp?(timestamp)
68
+ timestamp && timestamp.is_a?(Integer) && timestamp > 999999999 && timestamp < 100000000000
69
+ end
70
+
71
+
88
72
  def verify_response(response)
89
73
  if response.code >= 200 && response.code < 300
90
74
  response
@@ -98,35 +82,6 @@ module Customerio
98
82
  hash.inject({}){ |hash, (k,v)| hash[k.to_sym] = v; hash }
99
83
  end
100
84
 
101
- def attributes_from(customer)
102
- if id?(customer)
103
- { :id => customer }
104
- else
105
- {
106
- :id => id_from(customer),
107
- :email => customer.email,
108
- :created_at => customer.created_at.to_i
109
- }
110
- end
111
- end
112
-
113
- def id_from(customer)
114
- if id?(customer)
115
- customer
116
- else
117
- warn "[DEPRECATION] Passing a customer object to Customerio::Client is deprecated. Just pass a hash with an id key."
118
- customer.id
119
- end
120
- end
121
-
122
- def custom_id(id)
123
- @@id_block ? @@id_block.call(id) : id
124
- end
125
-
126
- def id?(object)
127
- object.is_a?(Integer) || object.is_a?(String)
128
- end
129
-
130
85
  def options
131
86
  { :basic_auth => @auth }
132
87
  end
@@ -1,3 +1,3 @@
1
1
  module Customerio
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -76,13 +76,26 @@ key information changes. This keeps [Customer.io](http://customer.io) up to date
76
76
  # must at least pass in an id, email, and created_at timestamp.
77
77
 
78
78
  $customerio.identify(
79
- id: 5,
80
- email: "bob@example.com,
81
- created_at: customer.created_at.to_i,
82
- first_name: "Bob",
83
- plan: "basic"
79
+ :id => 5,
80
+ :email => "bob@example.com,
81
+ :created_at => customer.created_at.to_i,
82
+ :first_name => "Bob",
83
+ :plan => "basic"
84
84
  )
85
85
 
86
+ ### Deleting customers
87
+
88
+ Deleting a customer will remove them, and all their information from
89
+ Customer.io. Note: if you're still sending data to Customer.io via
90
+ other means (such as the javascript snippet), the customer could be
91
+ recreated.
92
+
93
+ # Arguments
94
+ # customer_id (required) - a unique identifier for the customer. This
95
+ # should be the same id you'd pass into the
96
+ # `identify` command above.
97
+
98
+ $customerio.delete(5)
86
99
 
87
100
  ### Tracking a custom event
88
101
 
@@ -98,7 +111,12 @@ encourage your customers to perform an action.
98
111
  # event. These attributes can be used in your triggers to control who should
99
112
  # receive the triggered email. You can set any number of data values.
100
113
 
101
- $customerio.track(5, "purchase", type: "socks", price: "13.99")
114
+ $customerio.track(5, "purchase", :type => "socks", :price => "13.99")
115
+
116
+ **Note:** If you'd like to track events which occurred in the past, you can include a `timestamp` attribute
117
+ (in seconds since the epoch), and we'll use that as the date the event occurred.
118
+
119
+ $customerio.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => 1365436200)
102
120
 
103
121
  ## Contributing
104
122
 
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe Customerio::Client do
4
4
  let(:client) { Customerio::Client.new("SITE_ID", "API_KEY") }
5
- let(:customer) { mock("Customer", :id => 5, :email => "customer@example.com", :created_at => Time.now) }
6
5
  let(:response) { mock("Response", :code => 200) }
7
6
 
8
7
  before do
@@ -13,7 +12,7 @@ describe Customerio::Client do
13
12
 
14
13
  describe ".base_uri" do
15
14
  it "should be set to customer.io's api" do
16
- Customerio::Client.base_uri.should == "https://app.customer.io"
15
+ Customerio::Client.base_uri.should == "https://track.customer.io"
17
16
  end
18
17
  end
19
18
 
@@ -55,85 +54,6 @@ describe Customerio::Client do
55
54
  it "requires an id attribute" do
56
55
  lambda { client.identify(:email => "customer@example.com") }.should raise_error(Customerio::Client::MissingIdAttributeError)
57
56
  end
58
-
59
- context "customer object passed in" do
60
- it "sends the customer's id, email, and created_at timestamp" do
61
- Customerio::Client.should_receive(:put).with("/api/v1/customers/5", {
62
- :basic_auth => anything(),
63
- :body => {
64
- :id => 5,
65
- :email => "customer@example.com",
66
- :created_at => Time.now.to_i
67
- }
68
- }).and_return(response)
69
-
70
- client.identify(customer)
71
- end
72
-
73
- it "sends any optional attributes" do
74
- Customerio::Client.should_receive(:put).with("/api/v1/customers/5", {
75
- :basic_auth => anything(),
76
- :body => {
77
- :id => 5,
78
- :email => "customer@example.com",
79
- :created_at => Time.now.to_i,
80
- :first_name => "Bob",
81
- :plan => "basic"
82
- }
83
- }).and_return(response)
84
-
85
- client.identify(customer, :first_name => "Bob", :plan => "basic")
86
- end
87
-
88
- it "allows customer object attributes to be overriden" do
89
- Customerio::Client.should_receive(:put).with("/api/v1/customers/5", {
90
- :basic_auth => anything(),
91
- :body => {
92
- :id => 5,
93
- :email => "customer2@example.com",
94
- :created_at => Time.now.to_i,
95
- :first_name => "Bob",
96
- :plan => "basic"
97
- }
98
- }).and_return(response)
99
-
100
- client.identify(customer, "email" => "customer2@example.com", :first_name => "Bob", :plan => "basic")
101
- end
102
- end
103
-
104
- context "client has customized identities" do
105
- before do
106
- Customerio::Client.id do |customer_id|
107
- "production_#{customer_id}"
108
- end
109
- end
110
-
111
- it "identifies the customer with the identification method" do
112
- Customerio::Client.should_receive(:put).with("/api/v1/customers/production_5", {
113
- :basic_auth => anything(),
114
- :body => {
115
- :id => "production_5",
116
- :email => "customer@example.com",
117
- :created_at => Time.now.to_i
118
- }
119
- }).and_return(response)
120
-
121
- client.identify(customer)
122
- end
123
-
124
- it "uses custom identity when using a pure hash" do
125
- Customerio::Client.should_receive(:put).with("/api/v1/customers/production_5", {
126
- :basic_auth => anything(),
127
- :body => {
128
- :id => "production_5",
129
- :email => "customer@example.com",
130
- :created_at => Time.now.to_i
131
- }
132
- }).and_return(response)
133
-
134
- client.identify(:id => 5, :email => "customer@example.com", :created_at => Time.now.to_i)
135
- end
136
- end
137
57
  end
138
58
 
139
59
  describe "#delete" do
@@ -146,26 +66,21 @@ describe Customerio::Client do
146
66
  describe "#track" do
147
67
  it "sends a POST request to the customer.io's event API" do
148
68
  Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", anything()).and_return(response)
149
- client.track(customer, "purchase")
69
+ client.track(5, "purchase")
150
70
  end
151
71
 
152
72
  it "raises an error if POST doesn't return a 2xx response code" do
153
73
  Customerio::Client.should_receive(:post).and_return(mock("Response", :code => 500))
154
- lambda { client.track(customer, "purchase") }.should raise_error(Customerio::Client::InvalidResponse)
74
+ lambda { client.track(5, "purchase") }.should raise_error(Customerio::Client::InvalidResponse)
155
75
  end
156
76
 
157
- it "calls identify with the user's attributes to ensure they've been properly identified" do
158
- client.should_receive(:identify).with({ :id => 5, :email => "customer@example.com", :created_at => Time.now.to_i }).and_return(response)
159
- client.track(customer, "purchase")
160
- end
161
-
162
77
  it "uses the site_id and api key for basic auth" do
163
78
  Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", {
164
79
  :basic_auth => { :username => "SITE_ID", :password => "API_KEY" },
165
80
  :body => anything()
166
81
  })
167
82
 
168
- client.track(customer, "purchase")
83
+ client.track(5, "purchase")
169
84
  end
170
85
 
171
86
  it "sends the event name" do
@@ -174,7 +89,7 @@ describe Customerio::Client do
174
89
  :body => { :name => "purchase", :data => {} }
175
90
  }).and_return(response)
176
91
 
177
- client.track(customer, "purchase")
92
+ client.track(5, "purchase")
178
93
  end
179
94
 
180
95
  it "sends any optional event attributes" do
@@ -186,45 +101,58 @@ describe Customerio::Client do
186
101
  }
187
102
  }).and_return(response)
188
103
 
189
- client.track(customer, "purchase", :type => "socks", :price => "13.99")
104
+ client.track(5, "purchase", :type => "socks", :price => "13.99")
105
+ end
106
+
107
+ it "allows sending of a timestamp" do
108
+ Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", {
109
+ :basic_auth => anything(),
110
+ :body => {
111
+ :name => "purchase",
112
+ :data => { :type => "socks", :price => "13.99", :timestamp => 1561231234 },
113
+ :timestamp => 1561231234
114
+ }
115
+ }).and_return(response)
116
+
117
+ client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234)
190
118
  end
191
119
 
192
- it "allows tracking by customer id as well" do
120
+ it "doesn't send timestamp if timestamp is in milliseconds" do
193
121
  Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", {
194
122
  :basic_auth => anything(),
195
123
  :body => {
196
124
  :name => "purchase",
197
- :data => { :type => "socks", :price => "13.99" }
125
+ :data => { :type => "socks", :price => "13.99", :timestamp => 1561231234000 }
198
126
  }
199
127
  }).and_return(response)
200
128
 
201
- client.track(5, "purchase", :type => "socks", :price => "13.99")
129
+ client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234000)
202
130
  end
203
131
 
204
- context "client has customized identities" do
205
- before do
206
- Customerio::Client.id do |customer_id|
207
- "production_#{customer_id}"
208
- end
209
- end
132
+ it "doesn't send timestamp if timestamp is a date" do
133
+ date = Time.now
210
134
 
211
- it "identifies the customer with the identification method" do
212
- Customerio::Client.should_receive(:post).with("/api/v1/customers/production_5/events", {
213
- :basic_auth => anything(),
214
- :body => anything()
215
- }).and_return(response)
135
+ Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", {
136
+ :basic_auth => anything(),
137
+ :body => {
138
+ :name => "purchase",
139
+ :data => { :type => "socks", :price => "13.99", :timestamp => date }
140
+ }
141
+ }).and_return(response)
216
142
 
217
- client.track(customer, "purchase")
218
- end
143
+ client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => date)
144
+ end
219
145
 
220
- it "uses the identification method when tracking by id" do
221
- Customerio::Client.should_receive(:post).with("/api/v1/customers/production_5/events", {
222
- :basic_auth => anything(),
223
- :body => anything()
224
- }).and_return(response)
146
+ it "doesn't send timestamp if timestamp isn't a integer" do
147
+ Customerio::Client.should_receive(:post).with("/api/v1/customers/5/events", {
148
+ :basic_auth => anything(),
149
+ :body => {
150
+ :name => "purchase",
151
+ :data => { :type => "socks", :price => "13.99", :timestamp => "Hello world" }
152
+ }
153
+ }).and_return(response)
225
154
 
226
- client.track(5, "purchase")
227
- end
155
+ client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => "Hello world")
228
156
  end
229
157
 
230
158
  context "tracking an anonymous event" do
@@ -262,6 +190,19 @@ describe Customerio::Client do
262
190
 
263
191
  client.track("purchase", :type => "socks", :price => "13.99")
264
192
  end
193
+
194
+ it "allows sending of a timestamp" do
195
+ Customerio::Client.should_receive(:post).with("/api/v1/events", {
196
+ :basic_auth => anything(),
197
+ :body => {
198
+ :name => "purchase",
199
+ :data => { :type => "socks", :price => "13.99", :timestamp => 1561231234 },
200
+ :timestamp => 1561231234
201
+ }
202
+ }).and_return(response)
203
+
204
+ client.track("purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234)
205
+ end
265
206
  end
266
207
  end
267
208
  end
@@ -5,9 +5,3 @@ require 'customerio'
5
5
  require 'fakeweb'
6
6
 
7
7
  FakeWeb.allow_net_connect = false
8
-
9
- RSpec.configure do |config|
10
- config.before(:each) do
11
- Customerio::Client.default_config
12
- end
13
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: customerio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-18 00:00:00.000000000 Z
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty