customerio 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.markdown +13 -0
- data/Gemfile.lock +2 -2
- data/lib/customerio/client.rb +12 -57
- data/lib/customerio/version.rb +1 -1
- data/readme.markdown +24 -6
- data/spec/client_spec.rb +55 -114
- data/spec/spec_helper.rb +0 -6
- metadata +2 -2
data/CHANGELOG.markdown
CHANGED
@@ -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
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
customerio (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.
|
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)
|
data/lib/customerio/client.rb
CHANGED
@@ -3,36 +3,16 @@ require 'httparty'
|
|
3
3
|
module Customerio
|
4
4
|
class Client
|
5
5
|
include HTTParty
|
6
|
-
base_uri 'https://
|
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(
|
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
|
-
|
33
|
+
customer_id, event_name = args
|
54
34
|
|
55
|
-
|
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/#{
|
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
|
data/lib/customerio/version.rb
CHANGED
data/readme.markdown
CHANGED
@@ -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
|
80
|
-
email
|
81
|
-
created_at
|
82
|
-
first_name
|
83
|
-
plan
|
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
|
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
|
|
data/spec/client_spec.rb
CHANGED
@@ -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://
|
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(
|
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(
|
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(
|
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(
|
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(
|
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 "
|
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
|
-
|
205
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
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
|
-
|
218
|
-
|
143
|
+
client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => date)
|
144
|
+
end
|
219
145
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
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
|
-
|
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
|
data/spec/spec_helper.rb
CHANGED
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
|
+
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-
|
12
|
+
date: 2013-04-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|