customerio 4.0.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbff37c21ea57a934d671356e89ef06114170d0b753c91048c255b399ce146de
4
- data.tar.gz: 1d225801d24005870b63aa2f95850b47cef6ef822f7f3132ea9b7378cffaa852
3
+ metadata.gz: 16635bdd8c1cfb5e77fbe0c29ca18a69fdbcd48b3824a19a4657f4bb9d6d0991
4
+ data.tar.gz: ad565a4bf81cb86a956893bdc104bd0967971af84b4dfcb453f47ac6fae0b6ea
5
5
  SHA512:
6
- metadata.gz: c41f22bc7fe6038432cd9e854c5bd18cd4b117f2320d02c3e142f5256cf0626de05e982db9676fdc3feed48cd26a6343e10717c196ab0e22b7d3798d4b5bb444
7
- data.tar.gz: f70520dda7f7defab832cc4efc85771c10e3e042aff034512a261b630f73db2f63474b8103dbf43e4e98be29a0e03a20b0993f1a9e31871f84e2fad41d6d0f8c
6
+ metadata.gz: 6b944374f304906b7533def39708eb07078390e07a413bf3bec11f46aecc65683a88c1a8d89bf50d65b16fdc2d5c561f2a0b484827c8ac828b3857cf101efba5
7
+ data.tar.gz: 17fe083a74d404f9d243e0c9e0a9713e4f02fb4009d10807d30f50d192ce020ba33065684bd84aadaf02908fc9de55d950b5f23d9549ffadce1cb36502f2bc8d
@@ -1,30 +1,21 @@
1
- name: ruby_ci
1
+ name: ci
2
2
 
3
3
  on: [push,pull_request]
4
4
 
5
5
  jobs:
6
- build:
6
+ test:
7
7
  strategy:
8
8
  matrix:
9
9
  ruby: ['2.5', '2.6', '2.7']
10
- runs-on: ubuntu-latest
10
+ runs-on: ubuntu-latest
11
+ env:
12
+ BUNDLE_PATH: ${{ github.workspace }}/vendor/bundle
11
13
  steps:
12
14
  - uses: actions/checkout@v2
13
- - name: set up ruby
14
- uses: actions/setup-ruby@v1
15
+ - uses: ruby/setup-ruby@v1
15
16
  with:
16
17
  ruby-version: ${{ matrix.ruby }}
17
- - name: install bundle
18
- run: |
19
- sudo apt-get -yqq install libpq-dev
20
- gem install bundler
21
- - name: Cache dependencies
22
- uses: actions/cache@v2
23
- with:
24
- path: vendor/bundle
25
- key: customerio-${{ matrix.ruby }}-${{ hashFiles('customerio.gemspec') }}
26
- restore-keys: |
27
- customerio-${{ matrix.ruby }}-
28
- - name: Install dependencies
29
- run: bundle install --path vendor/bundle
30
- - run: bundle exec rspec
18
+ bundler-cache: true
19
+
20
+ - name: Unit Test w/ RSpec
21
+ run: bundle exec rspec
data/.gitpod.yml ADDED
@@ -0,0 +1,10 @@
1
+ tasks:
2
+ - init: |
3
+ bundle config set --local path 'vendor/bundle'
4
+ bundle install
5
+
6
+ vscode:
7
+ extensions:
8
+ - connorshea.vscode-ruby-test-adapter
9
+ - hbenl.vscode-test-explorer
10
+ - hbenl.test-adapter-converter
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ ## Customerio 4.1.0 - Sep 27, 2021
2
+ ### Added
3
+ - Added support for [merge customers](https://customer.io/docs/api/#operation/merge) API
4
+
1
5
  ## Customerio 4.0.1 - July 13, 2021
2
6
  ### Changed
3
7
  - Update addressable gem dependency to v2.8.0
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
- # Customerio
1
+ <p align="center">
2
+ <a href="https://customer.io">
3
+ <img src="https://files.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LSFjPaMQn1zKdYh6i89%2F-LU6OglGKqQfqMd5Zl-V%2F-LU6OzOLnOvy8VLwfgdg%2FLogo-Color-Horizontal.png?alt=media&token=add29dd0-cabb-4440-b46b-aed21350ae90" height="60">
4
+ </a>
5
+ <p align="center">Power automated communication that people like to receive.</p>
6
+ </p>
2
7
 
3
- A ruby client for the [Customer.io](http://customer.io) [event API](http://learn.customer.io/api/).
8
+ [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blueviolet?logo=gitpod)](https://gitpod.io/#https://github.com/customerio/customerio-ruby/)
9
+ [![ci](https://github.com/customerio/customerio-ruby/actions/workflows/main.yml/badge.svg)](https://github.com/customerio/customerio-ruby/actions/workflows/main.yml)
4
10
 
5
- [![Build Status](https://secure.travis-ci.org/customerio/customerio-ruby.png?branch=master)](http://travis-ci.org/customerio/customerio-ruby)
6
- [![Code Climate](https://codeclimate.com/github/customerio/customerio-ruby/badges/gpa.svg)](https://codeclimate.com/github/customerio/customerio-ruby)
11
+ # Customer.io Ruby
12
+
13
+ A ruby client for the [Customer.io Track API](https://customer.io/docs/api/#tag/trackOverview).
7
14
 
8
15
  ## Installation
9
16
 
@@ -24,7 +31,7 @@ Or install it yourself:
24
31
  ### Before we get started: API client vs. JavaScript snippet
25
32
 
26
33
  It's helpful to know that everything below can also be accomplished
27
- through the [Customer.io JavaScript snippet](http://learn.customer.io/developer-documentation/javascript-quick-start.html).
34
+ through the [Customer.io JavaScript snippet](https://customer.io/docs/javascript-quick-start/).
28
35
 
29
36
  In many cases, using the JavaScript snippet will be easier to integrate with
30
37
  your app, but there are several reasons why using the API client is useful:
@@ -38,7 +45,7 @@ your app, but there are several reasons why using the API client is useful:
38
45
 
39
46
  In the end, the decision on whether or not to use the API client or
40
47
  the JavaScript snippet should be based on what works best for you.
41
- You'll be able to integrate **fully** with [Customer.io](http://customer.io) with either approach.
48
+ You'll be able to integrate **fully** with [Customer.io](https://customer.io) with either approach.
42
49
 
43
50
  ### Setup
44
51
 
@@ -54,9 +61,9 @@ $customerio = Customerio::Client.new("YOUR SITE ID", "YOUR API SECRET KEY", regi
54
61
 
55
62
  ### Identify logged in customers
56
63
 
57
- Tracking data of logged in customers is a key part of [Customer.io](http://customer.io). In order to
64
+ Tracking data of logged in customers is a key part of [Customer.io](https://customer.io). In order to
58
65
  send triggered emails, we must know the email address of the customer. You can
59
- also specify any number of customer attributes which help tailor [Customer.io](http://customer.io) to your
66
+ also specify any number of customer attributes which help tailor [Customer.io](https://customer.io) to your
60
67
  business.
61
68
 
62
69
  Attributes you specify are useful in several ways:
@@ -71,7 +78,7 @@ set up triggers which are only sent to customers who have subscribed to a
71
78
  particular plan (e.g. "premium").
72
79
 
73
80
  You'll want to indentify your customers when they sign up for your app and any time their
74
- key information changes. This keeps [Customer.io](http://customer.io) up to date with your customer information.
81
+ key information changes. This keeps [Customer.io](https://customer.io) up to date with your customer information.
75
82
 
76
83
  ```ruby
77
84
  # Arguments
@@ -104,9 +111,24 @@ recreated.
104
111
  $customerio.delete(5)
105
112
  ```
106
113
 
114
+ ### Merge duplicate customer profiles
115
+
116
+ When you merge two people, you pick a primary person and merge a secondary, duplicate person into it. The primary person remains after the merge and the secondary is deleted. This process is permanent: you cannot recover the secondary person.
117
+
118
+ The first and third parameters represent the identifier for the primary and secondary people respectively—one of `id`, `email`, or `cio_id`. The second and fourth parameters are the identifier values for the primary and secondary people respectively.
119
+
120
+ ```ruby
121
+ # $customerio.merge_customers("primaryType", "primaryIdentifier", "secondaryType", "secondaryIdentifier")
122
+ # primaryType / secondaryType are one of "id", "email", or "cio_id"
123
+ # primaryIdentifier / secondaryIdentifier are the identifier value corresponding to the type.
124
+
125
+ # merge customer "cperson@gmail.com" into "cool.person@company.com"
126
+ $customerio.merge_customers("email", "cool.person@company.com", "email", "cperson@gmail.com")
127
+ ```
128
+
107
129
  ### Tracking a custom event
108
130
 
109
- Now that you're identifying your customers with [Customer.io](http://customer.io), you can now send events like
131
+ Now that you're identifying your customers with [Customer.io](https://customer.io), you can now send events like
110
132
  "purchased" or "watchedIntroVideo". These allow you to more specifically target your users
111
133
  with automated emails, and track conversions when you're sending automated emails to
112
134
  encourage your customers to perform an action.
@@ -137,15 +159,22 @@ Anonymous events cannot trigger campaigns by themselves. To trigger a campaign,
137
159
 
138
160
  ```ruby
139
161
  # Arguments
140
- # anonymous_id (required) - the id representing the unknown person.
141
- # name (required) - the name of the event you want to track.
142
- # attributes (optional) - any related information you want to attach to the
143
- # event.
162
+ # anonymous_id (required, nullable) - the id representing the unknown person.
163
+ # name (required) - the name of the event you want to track.
164
+ # attributes (optional) - related information you want to attach to the event.
144
165
 
145
166
  $customerio.track_anonymous(anonymous_id, "product_view", :type => "socks" )
146
167
  ```
147
168
 
148
- Use the `recipient` attribute to specify the email address to send the messages to. [See our documentation on how to use anonymous events for more details](https://learn.customer.io/recipes/invite-emails.html).
169
+ Use the `recipient` attribute to specify the email address to send the messages to. [See our documentation on how to use anonymous events for more details](https://customer.io/docs/invite-emails/).
170
+
171
+ #### Anonymous invite events
172
+
173
+ If you previously sent [invite events](https://customer.io/docs/anonymous-invite-emails/), you can achieve the same functionality by sending an anonymous event with `nil` for the anonymous identifier. To send anonymous invites, your event *must* include a `recipient` attribute.
174
+
175
+ ```ruby
176
+ $customerio.track_anonymous(nil, "invite", :recipient => "new.person@example.com" )
177
+ ```
149
178
 
150
179
  ### Adding a mobile device
151
180
 
@@ -172,7 +201,7 @@ $customerio.delete_device(5, "my_device_token")
172
201
 
173
202
  ### Suppress a user
174
203
 
175
- Deletes the customer with the provided id if it exists and suppresses all future events and identifies for for that customer.
204
+ Deletes the customer with the provided id if it exists and suppresses all future events and identifies for that customer.
176
205
 
177
206
  ```ruby
178
207
  $customerio.suppress(5)
data/customerio.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency('addressable', '~> 2.8.0')
21
21
 
22
22
  gem.add_development_dependency('rake', '~> 10.5')
23
- gem.add_development_dependency('rspec', '3.3.0')
23
+ gem.add_development_dependency('rspec', '~> 3.10')
24
24
  gem.add_development_dependency('webmock', '3.6.0')
25
25
  gem.add_development_dependency('json')
26
26
  end
@@ -44,6 +44,8 @@ module Customerio
44
44
 
45
45
  req = request_class(method).new(uri.path)
46
46
 
47
+ headers['User-Agent'] = "Customer.io Ruby Client/" + Customerio::VERSION
48
+
47
49
  if @auth.has_key?(:site_id) && @auth.has_key?(:api_key)
48
50
  req.initialize_http_header(headers)
49
51
  req.basic_auth @auth[:site_id], @auth[:api_key]
@@ -1,6 +1,12 @@
1
1
  require "addressable/uri"
2
2
 
3
3
  module Customerio
4
+ class IdentifierType
5
+ ID = "id"
6
+ EMAIL = "email"
7
+ CIOID = "cio_id"
8
+ end
9
+
4
10
  class Client
5
11
  PUSH_OPENED = 'opened'
6
12
  PUSH_CONVERTED = 'converted'
@@ -46,7 +52,6 @@ module Customerio
46
52
  end
47
53
 
48
54
  def track_anonymous(anonymous_id, event_name, attributes = {})
49
- raise ParamError.new("anonymous_id must be a non-empty string") if is_empty?(anonymous_id)
50
55
  raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
51
56
 
52
57
  create_anonymous_event(anonymous_id, event_name, attributes)
@@ -91,6 +96,17 @@ module Customerio
91
96
  @client.request_and_verify_response(:post, track_push_notification_event_path, attributes.merge(event: event_name))
92
97
  end
93
98
 
99
+ def merge_customers(primary_id_type, primary_id, secondary_id_type, secondary_id)
100
+ raise ParamError.new("invalid primary_id_type") if !is_valid_id_type?(primary_id_type)
101
+ raise ParamError.new("primary_id must be a non-empty string") if is_empty?(primary_id)
102
+ raise ParamError.new("invalid secondary_id_type") if !is_valid_id_type?(secondary_id_type)
103
+ raise ParamError.new("secondary_id must be a non-empty string") if is_empty?(secondary_id)
104
+
105
+ body = { :primary => {primary_id_type => primary_id}, :secondary => {secondary_id_type => secondary_id} }
106
+
107
+ @client.request_and_verify_response(:post, merge_customers_path, body)
108
+ end
109
+
94
110
  private
95
111
 
96
112
  def escape(val)
@@ -122,6 +138,10 @@ module Customerio
122
138
  "/push/events"
123
139
  end
124
140
 
141
+ def merge_customers_path
142
+ "/api/v1/merge_customers"
143
+ end
144
+
125
145
  def create_or_update(attributes = {})
126
146
  attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
127
147
  raise MissingIdAttributeError.new("Must provide a customer id") if is_empty?(attributes[:id])
@@ -150,7 +170,7 @@ module Customerio
150
170
  def create_event(url:, event_name:, anonymous_id: nil, attributes: {})
151
171
  body = { :name => event_name, :data => attributes }
152
172
  body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
153
- body[:anonymous_id] = anonymous_id unless anonymous_id.nil?
173
+ body[:anonymous_id] = anonymous_id unless is_empty?(anonymous_id)
154
174
 
155
175
  @client.request_and_verify_response(:post, url, body)
156
176
  end
@@ -162,5 +182,9 @@ module Customerio
162
182
  def is_empty?(val)
163
183
  val.nil? || (val.is_a?(String) && val.strip == "")
164
184
  end
185
+
186
+ def is_valid_id_type?(input)
187
+ [IdentifierType::ID, IdentifierType::CIOID, IdentifierType::EMAIL].include? input
188
+ end
165
189
  end
166
190
  end
@@ -1,3 +1,3 @@
1
1
  module Customerio
2
- VERSION = "4.0.1"
2
+ VERSION = "4.3.0"
3
3
  end
@@ -14,7 +14,7 @@ describe Customerio::APIClient do
14
14
  end
15
15
 
16
16
  def request_headers
17
- { 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json' }
17
+ { 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
18
18
  end
19
19
 
20
20
  def json(data)
@@ -18,11 +18,11 @@ describe Customerio::BaseClient do
18
18
 
19
19
  def track_client_request_headers
20
20
  token = Base64.strict_encode64("#{site_id}:#{api_key}")
21
- { 'Authorization': "Basic #{token}", 'Content-Type': 'application/json' }
21
+ { 'Authorization': "Basic #{token}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
22
22
  end
23
23
 
24
24
  def api_client_request_headers
25
- { 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json' }
25
+ { 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
26
26
  end
27
27
 
28
28
  describe "with a site ID and API key" do
data/spec/client_spec.rb CHANGED
@@ -433,12 +433,20 @@ describe Customerio::Client do
433
433
  lambda { client.track_anonymous(anon_id, "purchase") }.should raise_error(Customerio::InvalidResponse)
434
434
  end
435
435
 
436
- it "throws an error when anonymous_id is missing" do
436
+ it "doesn't pass along anonymous_id if it is blank" do
437
437
  stub_request(:post, api_uri('/api/v1/events')).
438
- with(body: { anonymous_id: anon_id, name: "purchase", data: {} }).
439
- to_return(status: 500, body: "", headers: {})
438
+ with(body: { name: "some_event", data: {} }).
439
+ to_return(status: 200, body: "", headers: {})
440
+
441
+ client.track_anonymous("", "some_event")
442
+ end
443
+
444
+ it "doesn't pass along anonymous_id if it is nil" do
445
+ stub_request(:post, api_uri('/api/v1/events')).
446
+ with(body: { name: "some_event", data: {} }).
447
+ to_return(status: 200, body: "", headers: {})
440
448
 
441
- lambda { client.track_anonymous("", "some_event") }.should raise_error(Customerio::Client::ParamError)
449
+ client.track_anonymous(nil, "some_event")
442
450
  end
443
451
 
444
452
  it "throws an error when event_name is missing" do
@@ -592,4 +600,35 @@ describe Customerio::Client do
592
600
  }.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
593
601
  end
594
602
  end
603
+
604
+ describe "#merge_customers" do
605
+ before(:each) do
606
+ @client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
607
+ end
608
+
609
+ it "should raise validation errors on merge params" do
610
+ expect {
611
+ client.merge_customers("", "id1", Customerio::IdentifierType::ID, "id2")
612
+ }.to raise_error(Customerio::Client::ParamError, 'invalid primary_id_type')
613
+
614
+ expect {
615
+ client.merge_customers(Customerio::IdentifierType::EMAIL, "", Customerio::IdentifierType::ID, "id2")
616
+ }.to raise_error(Customerio::Client::ParamError, 'primary_id must be a non-empty string')
617
+
618
+ expect {
619
+ client.merge_customers(Customerio::IdentifierType::CIOID, "id1", "", "id2")
620
+ }.to raise_error(Customerio::Client::ParamError, 'invalid secondary_id_type')
621
+
622
+ expect {
623
+ client.merge_customers(Customerio::IdentifierType::ID, "id1", Customerio::IdentifierType::ID, "")
624
+ }.to raise_error(Customerio::Client::ParamError, 'secondary_id must be a non-empty string')
625
+ end
626
+
627
+ it "requires a valid customer_id when creating" do
628
+ stub_request(:post, api_uri('/api/v1/merge_customers')).
629
+ to_return(status: 200, body: "", headers: {})
630
+
631
+ client.merge_customers(Customerio::IdentifierType::ID, "ID1", Customerio::IdentifierType::EMAIL, "hello@company.com")
632
+ end
633
+ end
595
634
  end
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: 4.0.1
4
+ version: 4.3.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: 2021-07-13 00:00:00.000000000 Z
11
+ date: 2022-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.3.0
61
+ version: '3.10'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.3.0
68
+ version: '3.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ extra_rdoc_files: []
103
103
  files:
104
104
  - ".github/workflows/main.yml"
105
105
  - ".gitignore"
106
+ - ".gitpod.yml"
106
107
  - CHANGELOG.markdown
107
108
  - Gemfile
108
109
  - LICENSE
@@ -125,7 +126,7 @@ homepage: http://customer.io
125
126
  licenses:
126
127
  - MIT
127
128
  metadata: {}
128
- post_install_message:
129
+ post_install_message:
129
130
  rdoc_options: []
130
131
  require_paths:
131
132
  - lib
@@ -140,8 +141,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  - !ruby/object:Gem::Version
141
142
  version: '0'
142
143
  requirements: []
143
- rubygems_version: 3.0.1
144
- signing_key:
144
+ rubygems_version: 3.2.5
145
+ signing_key:
145
146
  specification_version: 4
146
147
  summary: A ruby client for the Customer.io event API.
147
148
  test_files: