customerio 5.0.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.markdown +8 -0
- data/README.md +60 -2
- data/lib/customerio/api.rb +19 -0
- data/lib/customerio/client.rb +10 -2
- data/lib/customerio/param_encoder.rb +1 -1
- data/lib/customerio/requests/send_push_request.rb +36 -0
- data/lib/customerio/version.rb +1 -1
- data/lib/customerio.rb +1 -0
- data/spec/api_client_spec.rb +84 -1
- data/spec/client_spec.rb +40 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ad688e060a453d3f02dfcdacc1407a4376fd355deb6feb6a531d4f2b9ebbad6
|
4
|
+
data.tar.gz: ea3401fa18f031f4ecb70fc79ee8817b0278294debe53f2f78adb403873f32a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b708a8aba7b91c3a270b2829cc7ba24cad4d72e8030f04cc266dcf97adcb9de8579f0fe159eeed5c95669890dd30376f05c28b43540894feb8dd15f25a516d4
|
7
|
+
data.tar.gz: 128500f502747de7b3d4e92a201ebcf23fa2ebe731f529fb57d72f2919f95f81f3cb8e59917a621e9e475c957c234302641581415d21cfa2189d3aa994889557
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## Customerio 5.2.0 - December 8, 2023
|
2
|
+
### Changed
|
3
|
+
- The `identify` method will now automatically use the `cio_id` attribute as the customer ID when calling the track service. This allows a customer to be updated using `identify` to modify the `id` and `email` attributes.
|
4
|
+
|
5
|
+
## Customerio 5.1.0 - May 5, 2023
|
6
|
+
### Added
|
7
|
+
- Added `send_push` to `APIClient` and `SendPushRequest` to support sending transactional push notifications.
|
8
|
+
|
1
9
|
## Customerio 4.3.1 - January 5, 2023
|
2
10
|
### Added
|
3
11
|
- Added the `disable_css_preprocessing` and `language` optional fields to send request
|
data/README.md
CHANGED
@@ -77,7 +77,7 @@ if you pass along the current subscription plan (free / basic / premium) for you
|
|
77
77
|
set up triggers which are only sent to customers who have subscribed to a
|
78
78
|
particular plan (e.g. "premium").
|
79
79
|
|
80
|
-
You'll want to
|
80
|
+
You'll want to identify your customers when they sign up for your app and any time their
|
81
81
|
key information changes. This keeps [Customer.io](https://customer.io) up to date with your customer information.
|
82
82
|
|
83
83
|
```ruby
|
@@ -95,6 +95,24 @@ $customerio.identify(
|
|
95
95
|
)
|
96
96
|
```
|
97
97
|
|
98
|
+
### Updating customers
|
99
|
+
|
100
|
+
You can use the identify operation to update customers.
|
101
|
+
If you need to change the `id` or `email` identifiers for a customer,
|
102
|
+
you will need to pass in the `cio_id` identifier.
|
103
|
+
`cio_id` is a unique identifier set by Customer.io, used to reference a person,
|
104
|
+
and cannot be changed.
|
105
|
+
|
106
|
+
E.g.: if the customer created in the identify operation above was given the `cio_id` of `"f000000d"`, you could change its ID and email address using:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
$customerio.identify(
|
110
|
+
:cio_id => "f000000d",
|
111
|
+
:id => 1005,
|
112
|
+
:email => "bob.fullname@example.com"
|
113
|
+
)
|
114
|
+
```
|
115
|
+
|
98
116
|
### Deleting customers
|
99
117
|
|
100
118
|
Deleting a customer will remove them, and all their information from
|
@@ -217,7 +235,9 @@ $customerio.unsuppress(5)
|
|
217
235
|
|
218
236
|
### Send Transactional Messages
|
219
237
|
|
220
|
-
To use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [app key](https://customer.io/docs/managing-credentials#app-api-keys).
|
238
|
+
To use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [app key](https://customer.io/docs/managing-credentials#app-api-keys) and create a request object of your message type.
|
239
|
+
|
240
|
+
#### Email
|
221
241
|
|
222
242
|
Create a new `SendEmailRequest` object containing:
|
223
243
|
|
@@ -262,6 +282,44 @@ rescue Customerio::InvalidResponse => e
|
|
262
282
|
end
|
263
283
|
```
|
264
284
|
|
285
|
+
#### Push
|
286
|
+
|
287
|
+
Create a new `SendPushRequest` object containing:
|
288
|
+
|
289
|
+
* `transactional_message_id`: the ID or trigger name of the transactional message you want to send.
|
290
|
+
* an `identifiers` object containing the `id` or `email` of your recipient. If the profile does not exist, Customer.io creates it.
|
291
|
+
|
292
|
+
Use `send_push` referencing your request to send a transactional message. [Learn more about transactional messages and `SendPushRequest` properties](https://customer.io/docs/transactional-api).
|
293
|
+
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
require "customerio"
|
297
|
+
|
298
|
+
client = Customerio::APIClient.new("your API key", region: Customerio::Regions::US)
|
299
|
+
|
300
|
+
request = Customerio::SendPushRequest.new(
|
301
|
+
transactional_message_id: "3",
|
302
|
+
message_data: {
|
303
|
+
name: "Person",
|
304
|
+
items: {
|
305
|
+
name: "shoes",
|
306
|
+
price: "59.99",
|
307
|
+
},
|
308
|
+
products: [],
|
309
|
+
},
|
310
|
+
identifiers: {
|
311
|
+
id: "2",
|
312
|
+
},
|
313
|
+
)
|
314
|
+
|
315
|
+
begin
|
316
|
+
response = client.send_push(request)
|
317
|
+
puts response
|
318
|
+
rescue Customerio::InvalidResponse => e
|
319
|
+
puts e.code, e.message
|
320
|
+
end
|
321
|
+
```
|
322
|
+
|
265
323
|
## Contributing
|
266
324
|
|
267
325
|
1. Fork it
|
data/lib/customerio/api.rb
CHANGED
@@ -26,10 +26,29 @@ module Customerio
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def send_push(req)
|
30
|
+
raise "request must be an instance of Customerio::SendPushRequest" unless req.is_a?(Customerio::SendPushRequest)
|
31
|
+
response = @client.request(:post, send_push_path, req.message)
|
32
|
+
|
33
|
+
case response
|
34
|
+
when Net::HTTPSuccess then
|
35
|
+
JSON.parse(response.body)
|
36
|
+
when Net::HTTPBadRequest then
|
37
|
+
json = JSON.parse(response.body)
|
38
|
+
raise Customerio::InvalidResponse.new(response.code, json['meta']['error'], response)
|
39
|
+
else
|
40
|
+
raise InvalidResponse.new(response.code, response.body)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
29
44
|
private
|
30
45
|
|
31
46
|
def send_email_path
|
32
47
|
"/v1/send/email"
|
33
48
|
end
|
49
|
+
|
50
|
+
def send_push_path
|
51
|
+
"/v1/send/push"
|
52
|
+
end
|
34
53
|
end
|
35
54
|
end
|
data/lib/customerio/client.rb
CHANGED
@@ -151,9 +151,17 @@ module Customerio
|
|
151
151
|
|
152
152
|
def create_or_update(attributes = {})
|
153
153
|
attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
|
154
|
-
|
154
|
+
if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id])
|
155
|
+
raise MissingIdAttributeError.new("Must provide a customer id")
|
156
|
+
end
|
155
157
|
|
156
|
-
|
158
|
+
# Use cio_id as the identifier, if present,
|
159
|
+
# to allow the id and email identifiers to be updated.
|
160
|
+
customer_id = attributes[:id]
|
161
|
+
if !is_empty?(attributes[:cio_id])
|
162
|
+
customer_id = "cio_" + attributes[:cio_id]
|
163
|
+
end
|
164
|
+
url = customer_path(customer_id)
|
157
165
|
@client.request_and_verify_response(:put, url, attributes)
|
158
166
|
end
|
159
167
|
|
@@ -55,7 +55,7 @@ module Customerio
|
|
55
55
|
param
|
56
56
|
end
|
57
57
|
|
58
|
-
# Prefer ERB::Util.url_encode, fall
|
58
|
+
# Prefer ERB::Util.url_encode, fall back to deprecation URI.encode for
|
59
59
|
# old Ruby support
|
60
60
|
def self.escape_value(value)
|
61
61
|
if ERB::Util.respond_to? :url_encode
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Customerio
|
2
|
+
class SendPushRequest
|
3
|
+
attr_reader :message
|
4
|
+
|
5
|
+
def initialize(opts)
|
6
|
+
@message = opts.delete_if { |field| invalid_field?(field) }
|
7
|
+
@message[:custom_device] = opts[:device] if opts[:device]
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
REQUIRED_FIELDS = %i(transactional_message_id identifiers)
|
13
|
+
|
14
|
+
OPTIONAL_FIELDS = %i(
|
15
|
+
to
|
16
|
+
title
|
17
|
+
message
|
18
|
+
disable_message_retention
|
19
|
+
send_to_unsubscribed
|
20
|
+
queue_draft
|
21
|
+
message_data
|
22
|
+
send_at
|
23
|
+
language
|
24
|
+
image_url
|
25
|
+
link
|
26
|
+
sound
|
27
|
+
custom_data
|
28
|
+
device
|
29
|
+
custom_device
|
30
|
+
)
|
31
|
+
|
32
|
+
def invalid_field?(field)
|
33
|
+
!REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/customerio/version.rb
CHANGED
data/lib/customerio.rb
CHANGED
data/spec/api_client_spec.rb
CHANGED
@@ -6,7 +6,7 @@ require 'tempfile'
|
|
6
6
|
describe Customerio::APIClient do
|
7
7
|
let(:app_key) { "appkey" }
|
8
8
|
|
9
|
-
let(:client)
|
9
|
+
let(:client) { Customerio::APIClient.new(app_key) }
|
10
10
|
let(:response) { double("Response", code: 200) }
|
11
11
|
|
12
12
|
def api_uri(path)
|
@@ -169,4 +169,87 @@ describe Customerio::APIClient do
|
|
169
169
|
req.message[:attachments].should eq({ "test" => Base64.strict_encode64("test-content") })
|
170
170
|
end
|
171
171
|
end
|
172
|
+
|
173
|
+
describe "#send_push" do
|
174
|
+
it "sends a POST request to the /api/send/push path" do
|
175
|
+
req = Customerio::SendPushRequest.new(
|
176
|
+
identifiers: {
|
177
|
+
id: 'c1',
|
178
|
+
},
|
179
|
+
transactional_message_id: 1,
|
180
|
+
)
|
181
|
+
|
182
|
+
stub_request(:post, api_uri('/v1/send/push'))
|
183
|
+
.with(headers: request_headers, body: req.message)
|
184
|
+
.to_return(status: 200, body: { delivery_id: 1 }.to_json, headers: {})
|
185
|
+
|
186
|
+
client.send_push(req).should eq({ "delivery_id" => 1 })
|
187
|
+
end
|
188
|
+
|
189
|
+
it "handles validation failures (400)" do
|
190
|
+
req = Customerio::SendPushRequest.new(
|
191
|
+
identifiers: {
|
192
|
+
id: 'c1',
|
193
|
+
},
|
194
|
+
transactional_message_id: 1,
|
195
|
+
)
|
196
|
+
|
197
|
+
err_json = { meta: { error: "example error" } }.to_json
|
198
|
+
|
199
|
+
stub_request(:post, api_uri('/v1/send/push'))
|
200
|
+
.with(headers: request_headers, body: req.message)
|
201
|
+
.to_return(status: 400, body: err_json, headers: {})
|
202
|
+
|
203
|
+
lambda { client.send_push(req) }.should(
|
204
|
+
raise_error(Customerio::InvalidResponse) { |error|
|
205
|
+
error.message.should eq "example error"
|
206
|
+
error.code.should eq "400"
|
207
|
+
}
|
208
|
+
)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "handles other failures (5xx)" do
|
212
|
+
req = Customerio::SendPushRequest.new(
|
213
|
+
identifiers: {
|
214
|
+
id: 'c1',
|
215
|
+
},
|
216
|
+
transactional_message_id: 1,
|
217
|
+
)
|
218
|
+
|
219
|
+
stub_request(:post, api_uri('/v1/send/push'))
|
220
|
+
.with(headers: request_headers, body: req.message)
|
221
|
+
.to_return(status: 500, body: "Server unavailable", headers: {})
|
222
|
+
|
223
|
+
lambda { client.send_push(req) }.should(
|
224
|
+
raise_error(Customerio::InvalidResponse) { |error|
|
225
|
+
error.message.should eq "Server unavailable"
|
226
|
+
error.code.should eq "500"
|
227
|
+
}
|
228
|
+
)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "sets custom_device correctly if device present in req" do
|
232
|
+
req = Customerio::SendPushRequest.new(
|
233
|
+
identifiers: {
|
234
|
+
id: 'c1',
|
235
|
+
},
|
236
|
+
transactional_message_id: 1,
|
237
|
+
device: {
|
238
|
+
platform: 'ios',
|
239
|
+
token: 'sample-token',
|
240
|
+
}
|
241
|
+
)
|
242
|
+
|
243
|
+
req.message[:custom_device].should eq({
|
244
|
+
platform: 'ios',
|
245
|
+
token: 'sample-token',
|
246
|
+
})
|
247
|
+
|
248
|
+
stub_request(:post, api_uri('/v1/send/push'))
|
249
|
+
.with(headers: request_headers, body: req.message)
|
250
|
+
.to_return(status: 200, body: { delivery_id: 2 }.to_json, headers: {})
|
251
|
+
|
252
|
+
client.send_push(req).should eq({ "delivery_id" => 2 })
|
253
|
+
end
|
254
|
+
end
|
172
255
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -172,6 +172,7 @@ describe Customerio::Client do
|
|
172
172
|
it "requires an id attribute" do
|
173
173
|
lambda { client.identify(email: "customer@example.com") }.should raise_error(Customerio::Client::MissingIdAttributeError)
|
174
174
|
lambda { client.identify(id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
|
175
|
+
lambda { client.identify(cio_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
|
175
176
|
end
|
176
177
|
|
177
178
|
it 'should not raise errors when attribute keys are strings' do
|
@@ -183,6 +184,45 @@ describe Customerio::Client do
|
|
183
184
|
|
184
185
|
lambda { client.identify(attributes) }.should_not raise_error()
|
185
186
|
end
|
187
|
+
|
188
|
+
it 'uses cio_id for customer id, when present, for id updates' do
|
189
|
+
stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
|
190
|
+
body: {
|
191
|
+
cio_id: "347f00d",
|
192
|
+
id: 5
|
193
|
+
}).to_return(status: 200, body: "", headers: {})
|
194
|
+
|
195
|
+
client.identify({
|
196
|
+
cio_id: "347f00d",
|
197
|
+
id: 5
|
198
|
+
})
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'uses cio_id for customer id, when present, for email updates' do
|
202
|
+
stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
|
203
|
+
body: {
|
204
|
+
cio_id: "347f00d",
|
205
|
+
email: "different.customer@example.com"
|
206
|
+
}).to_return(status: 200, body: "", headers: {})
|
207
|
+
|
208
|
+
client.identify({
|
209
|
+
cio_id: "347f00d",
|
210
|
+
email: "different.customer@example.com"
|
211
|
+
})
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'allows updates with cio_id as the only id' do
|
215
|
+
stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
|
216
|
+
body: {
|
217
|
+
cio_id: "347f00d",
|
218
|
+
location: "here"
|
219
|
+
}).to_return(status: 200, body: "", headers: {})
|
220
|
+
|
221
|
+
client.identify({
|
222
|
+
cio_id: "347f00d",
|
223
|
+
location: "here"
|
224
|
+
})
|
225
|
+
end
|
186
226
|
end
|
187
227
|
|
188
228
|
describe "#delete" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: customerio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Allison
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- lib/customerio/param_encoder.rb
|
118
118
|
- lib/customerio/regions.rb
|
119
119
|
- lib/customerio/requests/send_email_request.rb
|
120
|
+
- lib/customerio/requests/send_push_request.rb
|
120
121
|
- lib/customerio/version.rb
|
121
122
|
- spec/api_client_spec.rb
|
122
123
|
- spec/base_client_spec.rb
|
@@ -126,7 +127,7 @@ homepage: http://customer.io
|
|
126
127
|
licenses:
|
127
128
|
- MIT
|
128
129
|
metadata: {}
|
129
|
-
post_install_message:
|
130
|
+
post_install_message:
|
130
131
|
rdoc_options: []
|
131
132
|
require_paths:
|
132
133
|
- lib
|
@@ -141,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
142
|
- !ruby/object:Gem::Version
|
142
143
|
version: '0'
|
143
144
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
145
|
-
signing_key:
|
145
|
+
rubygems_version: 3.2.33
|
146
|
+
signing_key:
|
146
147
|
specification_version: 4
|
147
148
|
summary: A ruby client for the Customer.io event API.
|
148
149
|
test_files:
|