customerio 5.2.0 → 5.4.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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +3 -3
- data/CHANGELOG.markdown +9 -0
- data/README.md +34 -6
- data/customerio.gemspec +2 -1
- data/lib/customerio/api.rb +19 -0
- data/lib/customerio/client.rb +18 -1
- data/lib/customerio/requests/send_sms_request.rb +42 -0
- data/lib/customerio/version.rb +1 -1
- data/lib/customerio.rb +1 -0
- data/spec/api_client_spec.rb +59 -0
- data/spec/client_spec.rb +35 -1
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 315eb46a7117b5e0408a57f896c49bf7336003db16439780d119ddc8e4015a1a
|
4
|
+
data.tar.gz: 41ddd049e7978bb75e8c792dda18090e9ffe7e64a85079a2e4d56cbc097feb48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 895cf3b64c4f57ed636a2a80c7c356eb4387edd2f5c5c65d1d46b0a418330333f84f66407ef8d844adeeda13d6089ee00d3ce60d22790d17fa246622c291f9d9
|
7
|
+
data.tar.gz: f213766bfb67f9ad8d570292816bba51e7c6863fbcc15d98e4f1f75d80953b00813e9c531c5b84d013f5531e23f4f623dbe77e5d054ea1ccc125608ef00a343b
|
data/.github/workflows/main.yml
CHANGED
@@ -6,13 +6,13 @@ jobs:
|
|
6
6
|
test:
|
7
7
|
strategy:
|
8
8
|
matrix:
|
9
|
-
ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
|
9
|
+
ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
|
10
10
|
runs-on: ubuntu-latest
|
11
11
|
env:
|
12
12
|
BUNDLE_PATH: ${{ github.workspace }}/vendor/bundle
|
13
13
|
steps:
|
14
|
-
- uses: actions/checkout@
|
15
|
-
- uses: ruby/setup-ruby@v1
|
14
|
+
- uses: actions/checkout@v4
|
15
|
+
- uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1.229.0
|
16
16
|
with:
|
17
17
|
ruby-version: ${{ matrix.ruby }}
|
18
18
|
bundler-cache: true
|
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## Customerio 5.4.0 - June 13, 2025
|
2
|
+
### Changed
|
3
|
+
- Added `send_sms` to `APIClient` and `SendSMSRequest` to support sending transactional push notifications.
|
4
|
+
|
5
|
+
## Customerio 5.3.0 - December 8, 2023
|
6
|
+
### Changed
|
7
|
+
- The `identify` method has been updated to allow the customer ID to be specified separately from the attributes, using the `customer_id` attribute. This allows a person to be updated by identifying them by e.g.: their email address. Thanks to trwalzer, jrbeck and jeremyw for the original changes that this is based on.
|
8
|
+
- It is no longer possible to set the `customer_id` attribute on a person. This is a side-effect of the changes to the `identify` method.
|
9
|
+
|
1
10
|
## Customerio 5.2.0 - December 8, 2023
|
2
11
|
### Changed
|
3
12
|
- 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.
|
data/README.md
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
<p align=
|
1
|
+
<p align=center>
|
2
2
|
<a href="https://customer.io">
|
3
|
-
<img src="https://
|
3
|
+
<img src="https://avatars.githubusercontent.com/u/1152079?s=200&v=4" height="60">
|
4
4
|
</a>
|
5
|
-
<p align="center">Power automated communication that people like to receive.</p>
|
6
5
|
</p>
|
7
6
|
|
8
7
|
[](https://gitpod.io/#https://github.com/customerio/customerio-ruby/)
|
9
8
|
[](https://github.com/customerio/customerio-ruby/actions/workflows/main.yml)
|
10
9
|
|
11
|
-
# Customer.io Ruby
|
10
|
+
# Customer.io Ruby
|
12
11
|
|
13
|
-
A ruby client for the [Customer.io Track API](https://customer.io/docs/api
|
12
|
+
A ruby client for the [Customer.io Journeys Track API](https://customer.io/docs/api/track/).
|
14
13
|
|
15
14
|
## Installation
|
16
15
|
|
@@ -95,7 +94,7 @@ $customerio.identify(
|
|
95
94
|
)
|
96
95
|
```
|
97
96
|
|
98
|
-
### Updating customers
|
97
|
+
### Updating customers: Changing identifiers
|
99
98
|
|
100
99
|
You can use the identify operation to update customers.
|
101
100
|
If you need to change the `id` or `email` identifiers for a customer,
|
@@ -113,6 +112,35 @@ $customerio.identify(
|
|
113
112
|
)
|
114
113
|
```
|
115
114
|
|
115
|
+
This method requires either the `id` or `cio_id` for the person. It does not work with email addresses.
|
116
|
+
|
117
|
+
You can also use this method to make other updates to the person using the `cio_id`.
|
118
|
+
|
119
|
+
### Updating customers: Using email address
|
120
|
+
|
121
|
+
If you need to identify a person using their email address, then you can do so
|
122
|
+
by passing in a customer ID to the `identify` method. This allows you to specify
|
123
|
+
a customer ID that is different than the one used in the `id` attribute. E.g.:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
# Arguments
|
127
|
+
# customer_id (required) - the customer ID to use for this customer, may be an id, email address, or the cio_id.
|
128
|
+
# This will be used to construct the URL but not sent in the body attributes.
|
129
|
+
# attributes (required) - a hash of information about the customer. You can pass any
|
130
|
+
# information that would be useful in your triggers. You
|
131
|
+
# must at least pass in an id, email, and created_at timestamp.
|
132
|
+
|
133
|
+
$customerio.identify(
|
134
|
+
:customer_id => "bob@example.com",
|
135
|
+
:location => "Australia"
|
136
|
+
)
|
137
|
+
```
|
138
|
+
|
139
|
+
Note:
|
140
|
+
|
141
|
+
* If you want to use the `cio_id` in the `customer_id` field of `identify_customer_id`, you will need to prefix it with `"cio_"`. E.g.: `"cio_f000000d"` for a `cio_id` of `f000000d`.
|
142
|
+
* The `identify` method can identify the person using one of `customer_id`, `cio_id` or `id`. The order of precedence is `customer_id` > `cio_id` > `id`.
|
143
|
+
|
116
144
|
### Deleting customers
|
117
145
|
|
118
146
|
Deleting a customer will remove them, and all their information from
|
data/customerio.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["john@customer.io"]
|
7
7
|
gem.description = "A ruby client for the Customer.io event API."
|
8
8
|
gem.summary = "A ruby client for the Customer.io event API."
|
9
|
-
gem.homepage = "
|
9
|
+
gem.homepage = "https://customer.io"
|
10
10
|
gem.license = "MIT"
|
11
11
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
|
19
19
|
gem.add_dependency('multi_json', "~> 1.0")
|
20
20
|
gem.add_dependency('addressable', '~> 2.8.0')
|
21
|
+
gem.add_dependency('base64', '~> 0.3.0')
|
21
22
|
|
22
23
|
gem.add_development_dependency('rake', '~> 10.5')
|
23
24
|
gem.add_development_dependency('rspec', '~> 3.10')
|
data/lib/customerio/api.rb
CHANGED
@@ -41,6 +41,21 @@ module Customerio
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
def send_sms(req)
|
45
|
+
raise "request must be an instance of Customerio::SendSMSRequest" unless req.is_a?(Customerio::SendSMSRequest)
|
46
|
+
response = @client.request(:post, send_sms_path, req.message)
|
47
|
+
|
48
|
+
case response
|
49
|
+
when Net::HTTPSuccess then
|
50
|
+
JSON.parse(response.body)
|
51
|
+
when Net::HTTPBadRequest then
|
52
|
+
json = JSON.parse(response.body)
|
53
|
+
raise Customerio::InvalidResponse.new(response.code, json['meta']['error'], response)
|
54
|
+
else
|
55
|
+
raise InvalidResponse.new(response.code, response.body)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
44
59
|
private
|
45
60
|
|
46
61
|
def send_email_path
|
@@ -50,5 +65,9 @@ module Customerio
|
|
50
65
|
def send_push_path
|
51
66
|
"/v1/send/push"
|
52
67
|
end
|
68
|
+
|
69
|
+
def send_sms_path
|
70
|
+
"/v1/send/sms"
|
71
|
+
end
|
53
72
|
end
|
54
73
|
end
|
data/lib/customerio/client.rb
CHANGED
@@ -151,16 +151,33 @@ module Customerio
|
|
151
151
|
|
152
152
|
def create_or_update(attributes = {})
|
153
153
|
attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
|
154
|
-
if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id])
|
154
|
+
if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id]) && is_empty?(attributes[:customer_id])
|
155
155
|
raise MissingIdAttributeError.new("Must provide a customer id")
|
156
156
|
end
|
157
157
|
|
158
158
|
# Use cio_id as the identifier, if present,
|
159
159
|
# to allow the id and email identifiers to be updated.
|
160
|
+
# The person is identified by a customer ID, which is included
|
161
|
+
# in the path to the Track v1 API. Choose the ID in this order
|
162
|
+
# from highest to lowest precedence:
|
163
|
+
#
|
164
|
+
# 1. customer_id: "id", an email address, or "cio_id" value.
|
165
|
+
# Any "cio_id" values need to be prefixed "cio_"
|
166
|
+
# so that the Track v1 API knows it's a cio_id.
|
167
|
+
#
|
168
|
+
# 2. cio_id: The cio_id value (no prefix required).
|
169
|
+
#
|
170
|
+
# 3. id: The id value.
|
160
171
|
customer_id = attributes[:id]
|
161
172
|
if !is_empty?(attributes[:cio_id])
|
162
173
|
customer_id = "cio_" + attributes[:cio_id]
|
163
174
|
end
|
175
|
+
if !is_empty?(attributes[:customer_id])
|
176
|
+
customer_id = attributes[:customer_id]
|
177
|
+
end
|
178
|
+
# customer_id is not an attribute, so remove it.
|
179
|
+
attributes.delete(:customer_id)
|
180
|
+
|
164
181
|
url = customer_path(customer_id)
|
165
182
|
@client.request_and_verify_response(:put, url, attributes)
|
166
183
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Customerio
|
4
|
+
class SendSMSRequest
|
5
|
+
attr_reader :message
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@message = opts.delete_if { |field| invalid_field?(field) }
|
9
|
+
@message[:attachments] = {}
|
10
|
+
@message[:headers] = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def attach(name, data, encode: true)
|
14
|
+
raise "attachment #{name} already exists" if @message[:attachments].has_key?(name)
|
15
|
+
@message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
REQUIRED_FIELDS = %i(identifiers transactional_message_id)
|
21
|
+
|
22
|
+
OPTIONAL_FIELDS = %i(
|
23
|
+
message_data
|
24
|
+
from
|
25
|
+
to
|
26
|
+
disable_message_retention
|
27
|
+
send_to_unsubscribed
|
28
|
+
tracked
|
29
|
+
queue_draft
|
30
|
+
send_at
|
31
|
+
language
|
32
|
+
)
|
33
|
+
|
34
|
+
def invalid_field?(field)
|
35
|
+
!REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
|
36
|
+
end
|
37
|
+
|
38
|
+
def encode(data)
|
39
|
+
Base64.strict_encode64(data)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/customerio/version.rb
CHANGED
data/lib/customerio.rb
CHANGED
@@ -6,6 +6,7 @@ module Customerio
|
|
6
6
|
require "customerio/client"
|
7
7
|
require "customerio/requests/send_email_request"
|
8
8
|
require "customerio/requests/send_push_request"
|
9
|
+
require "customerio/requests/send_sms_request"
|
9
10
|
require "customerio/api"
|
10
11
|
require "customerio/param_encoder"
|
11
12
|
end
|
data/spec/api_client_spec.rb
CHANGED
@@ -252,4 +252,63 @@ describe Customerio::APIClient do
|
|
252
252
|
client.send_push(req).should eq({ "delivery_id" => 2 })
|
253
253
|
end
|
254
254
|
end
|
255
|
+
|
256
|
+
describe "#send_sms" do
|
257
|
+
it "sends a POST request to the /api/send/sms path" do
|
258
|
+
req = Customerio::SendSMSRequest.new(
|
259
|
+
identifiers: {
|
260
|
+
id: 'c1',
|
261
|
+
},
|
262
|
+
transactional_message_id: 1,
|
263
|
+
)
|
264
|
+
|
265
|
+
stub_request(:post, api_uri('/v1/send/sms'))
|
266
|
+
.with(headers: request_headers, body: req.message)
|
267
|
+
.to_return(status: 200, body: { delivery_id: 1 }.to_json, headers: {})
|
268
|
+
|
269
|
+
client.send_sms(req).should eq({ "delivery_id" => 1 })
|
270
|
+
end
|
271
|
+
|
272
|
+
it "handles validation failures (400)" do
|
273
|
+
req = Customerio::SendSMSRequest.new(
|
274
|
+
identifiers: {
|
275
|
+
id: 'c1',
|
276
|
+
},
|
277
|
+
transactional_message_id: 1,
|
278
|
+
)
|
279
|
+
|
280
|
+
err_json = { meta: { error: "example error" } }.to_json
|
281
|
+
|
282
|
+
stub_request(:post, api_uri('/v1/send/sms'))
|
283
|
+
.with(headers: request_headers, body: req.message)
|
284
|
+
.to_return(status: 400, body: err_json, headers: {})
|
285
|
+
|
286
|
+
lambda { client.send_sms(req) }.should(
|
287
|
+
raise_error(Customerio::InvalidResponse) { |error|
|
288
|
+
error.message.should eq "example error"
|
289
|
+
error.code.should eq "400"
|
290
|
+
}
|
291
|
+
)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "handles other failures (5xx)" do
|
295
|
+
req = Customerio::SendSMSRequest.new(
|
296
|
+
identifiers: {
|
297
|
+
id: 'c1',
|
298
|
+
},
|
299
|
+
transactional_message_id: 1,
|
300
|
+
)
|
301
|
+
|
302
|
+
stub_request(:post, api_uri('/v1/send/sms'))
|
303
|
+
.with(headers: request_headers, body: req.message)
|
304
|
+
.to_return(status: 500, body: "Server unavailable", headers: {})
|
305
|
+
|
306
|
+
lambda { client.send_sms(req) }.should(
|
307
|
+
raise_error(Customerio::InvalidResponse) { |error|
|
308
|
+
error.message.should eq "Server unavailable"
|
309
|
+
error.code.should eq "500"
|
310
|
+
}
|
311
|
+
)
|
312
|
+
end
|
313
|
+
end
|
255
314
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -173,6 +173,7 @@ describe Customerio::Client 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
175
|
lambda { client.identify(cio_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
|
176
|
+
lambda { client.identify(customer_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
|
176
177
|
end
|
177
178
|
|
178
179
|
it 'should not raise errors when attribute keys are strings' do
|
@@ -223,6 +224,39 @@ describe Customerio::Client do
|
|
223
224
|
location: "here"
|
224
225
|
})
|
225
226
|
end
|
227
|
+
|
228
|
+
it "uses provided id rather than id" do
|
229
|
+
stub_request(:put, api_uri('/api/v1/customers/1234')).
|
230
|
+
with(body: json(id: "5")).
|
231
|
+
to_return(status: 200, body: "", headers: {})
|
232
|
+
|
233
|
+
client.identify(
|
234
|
+
customer_id: "1234",
|
235
|
+
id: "5"
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
it "uses provided cio_id rather than id" do
|
240
|
+
stub_request(:put, api_uri('/api/v1/customers/cio_5')).
|
241
|
+
with(body: json(id: "5")).
|
242
|
+
to_return(status: 200, body: "", headers: {})
|
243
|
+
|
244
|
+
client.identify(
|
245
|
+
customer_id: "cio_5",
|
246
|
+
id: "5"
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "uses provided email rather than id" do
|
251
|
+
stub_request(:put, api_uri('/api/v1/customers/customer@example.com')).
|
252
|
+
with(body: json(id: "5")).
|
253
|
+
to_return(status: 200, body: "", headers: {})
|
254
|
+
|
255
|
+
client.identify(
|
256
|
+
customer_id: "customer@example.com",
|
257
|
+
id: "5"
|
258
|
+
)
|
259
|
+
end
|
226
260
|
end
|
227
261
|
|
228
262
|
describe "#delete" do
|
@@ -650,7 +684,7 @@ describe Customerio::Client do
|
|
650
684
|
}.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
|
651
685
|
end
|
652
686
|
end
|
653
|
-
|
687
|
+
|
654
688
|
describe "#merge_customers" do
|
655
689
|
before(:each) do
|
656
690
|
@client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
|
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.4.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:
|
11
|
+
date: 2025-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 2.8.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: base64
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.3.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.3.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,16 +132,17 @@ files:
|
|
118
132
|
- lib/customerio/regions.rb
|
119
133
|
- lib/customerio/requests/send_email_request.rb
|
120
134
|
- lib/customerio/requests/send_push_request.rb
|
135
|
+
- lib/customerio/requests/send_sms_request.rb
|
121
136
|
- lib/customerio/version.rb
|
122
137
|
- spec/api_client_spec.rb
|
123
138
|
- spec/base_client_spec.rb
|
124
139
|
- spec/client_spec.rb
|
125
140
|
- spec/spec_helper.rb
|
126
|
-
homepage:
|
141
|
+
homepage: https://customer.io
|
127
142
|
licenses:
|
128
143
|
- MIT
|
129
144
|
metadata: {}
|
130
|
-
post_install_message:
|
145
|
+
post_install_message:
|
131
146
|
rdoc_options: []
|
132
147
|
require_paths:
|
133
148
|
- lib
|
@@ -142,8 +157,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
157
|
- !ruby/object:Gem::Version
|
143
158
|
version: '0'
|
144
159
|
requirements: []
|
145
|
-
rubygems_version: 3.
|
146
|
-
signing_key:
|
160
|
+
rubygems_version: 3.0.3.1
|
161
|
+
signing_key:
|
147
162
|
specification_version: 4
|
148
163
|
summary: A ruby client for the Customer.io event API.
|
149
164
|
test_files:
|