amplitude-api 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AmplitudeAPI
2
4
  # AmplitudeAPI::Identification
3
5
  class Identification
@@ -16,7 +18,7 @@ class AmplitudeAPI
16
18
  # @param [ String ] user_id a user_id to associate with the identification
17
19
  # @param [ String ] device_id a device_id to associate with the identification
18
20
  # @param [ Hash ] user_properties various properties to attach to the user identification
19
- def initialize(user_id: '', device_id: nil, user_properties: {})
21
+ def initialize(user_id: "", device_id: nil, user_properties: {})
20
22
  self.user_id = user_id
21
23
  self.device_id = device_id if device_id
22
24
  self.user_properties = user_properties
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AmplitudeAPI
2
- VERSION = '0.1.1'.freeze
4
+ VERSION = "0.3.0"
3
5
  end
data/readme.md CHANGED
@@ -19,7 +19,7 @@ AmplitudeAPI.config.api_key = "abcdef123456"
19
19
 
20
20
 
21
21
  event = AmplitudeAPI::Event.new({
22
- user_id: "123",
22
+ user_id: "12345",
23
23
  event_type: "clicked on home",
24
24
  time: Time.now,
25
25
  insert_id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
@@ -42,12 +42,12 @@ AmplitudeAPI.config.api_key = "abcdef123456"
42
42
  # Configure your Amplitude Secret Key
43
43
  AmplitudeAPI.config.secret_key = "secretMcSecret"
44
44
 
45
- AmplitudeAPI.delete(user_ids: [233],
45
+ AmplitudeAPI.delete(user_ids: ["12345"],
46
46
  requester: "privacy@example.com"
47
47
  )
48
48
  ```
49
49
 
50
- Currently, we are using this in Rails and using ActiveJob to dispatch events asynchronously. I plan on moving
50
+ Currently, we are using this in Rails and using ActiveJob to dispatch events asynchronously. I plan on moving
51
51
  background/asynchronous support into this gem.
52
52
 
53
53
  ## What's Next
@@ -56,7 +56,7 @@ background/asynchronous support into this gem.
56
56
  * Configurable default account to use when no `user_id` present
57
57
 
58
58
  ## Other useful resources
59
- * [Amplitude HTTP Api Documentation](https://amplitude.zendesk.com/hc/en-us/articles/204771828)
59
+ * [Amplitude HTTP API V2 Api Documentation](https://developers.amplitude.com/docs/http-api-v2)
60
60
  * [Segment.io Amplitude integration](https://segment.com/docs/integrations/amplitude/)
61
61
 
62
62
  ## Contributing
@@ -1,277 +1,318 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe AmplitudeAPI::Event do
4
6
  user = Struct.new(:id)
5
7
 
6
- context 'with a user object' do
7
- describe '#body' do
8
+ context "with a user object" do
9
+ describe "#body" do
8
10
  it "populates with the user's id" do
9
11
  event = described_class.new(
10
12
  user_id: user.new(123),
11
- event_type: 'clicked on home'
13
+ event_type: "clicked on home"
12
14
  )
13
15
  expect(event.to_hash[:user_id]).to eq(123)
14
16
  end
15
17
  end
16
18
  end
17
19
 
18
- context 'with a user id' do
19
- describe '#body' do
20
+ context "with a user id" do
21
+ describe "#body" do
20
22
  it "populates with the user's id" do
21
23
  event = described_class.new(
22
24
  user_id: 123,
23
- event_type: 'clicked on home'
25
+ event_type: "clicked on home"
24
26
  )
25
27
  expect(event.to_hash[:user_id]).to eq(123)
26
28
  end
27
29
  end
28
30
  end
29
31
 
30
- context 'without a user' do
31
- describe '#body' do
32
- it 'populates with the unknown user' do
32
+ context "without a user" do
33
+ describe "#body" do
34
+ it "populates with the unknown user" do
33
35
  event = described_class.new(
34
36
  user_id: nil,
35
- event_type: 'clicked on home'
37
+ event_type: "clicked on home"
36
38
  )
37
39
  expect(event.to_hash[:user_id]).to eq(AmplitudeAPI::USER_WITH_NO_ACCOUNT)
38
40
  end
39
41
  end
40
42
  end
41
43
 
42
- describe 'init' do
43
- context 'attributes' do
44
- it 'accepts string attributes' do
44
+ describe "init" do
45
+ context "attributes" do
46
+ it "accepts string attributes" do
45
47
  time = Time.at(1_451_606_400_000 / 1_000)
46
48
  event = described_class.new(
47
- 'user_id' => 123,
48
- 'device_id' => 'abcd',
49
- 'event_type' => 'sausage',
50
- 'event_properties' => { 'a' => 'b' },
51
- 'user_properties' => { 'c' => 'd' },
52
- 'time' => time,
53
- 'ip' => '127.0.0.1',
54
- 'platform' => 'Web',
55
- 'country' => 'United States',
56
- 'insert_id' => 'bestId'
49
+ "user_id" => 123,
50
+ "device_id" => "abcd",
51
+ "event_type" => "sausage",
52
+ "event_properties" => { "a" => "b" },
53
+ "user_properties" => { "c" => "d" },
54
+ "time" => time,
55
+ "ip" => "127.0.0.1",
56
+ "platform" => "Web",
57
+ "country" => "United States",
58
+ "insert_id" => "bestId"
57
59
  )
58
60
 
59
- expect(event.to_hash).to eq(event_type: 'sausage',
61
+ expect(event.to_hash).to eq(event_type: "sausage",
60
62
  user_id: 123,
61
- device_id: 'abcd',
62
- event_properties: { 'a' => 'b' },
63
- user_properties: { 'c' => 'd' },
63
+ device_id: "abcd",
64
+ event_properties: { "a" => "b" },
65
+ user_properties: { "c" => "d" },
64
66
  time: 1_451_606_400_000,
65
- ip: '127.0.0.1',
66
- platform: 'Web',
67
- country: 'United States',
68
- insert_id: 'bestId')
67
+ ip: "127.0.0.1",
68
+ platform: "Web",
69
+ country: "United States",
70
+ insert_id: "bestId")
69
71
  end
70
72
 
71
- it 'accepts symbol attributes' do
73
+ it "accepts symbol attributes" do
72
74
  time = Time.at(1_451_606_400_000 / 1_000)
73
75
  event = described_class.new(
74
76
  user_id: 123,
75
- device_id: 'abcd',
76
- event_type: 'sausage',
77
- event_properties: { 'a' => 'b' },
78
- user_properties: { 'c' => 'd' },
77
+ device_id: "abcd",
78
+ event_type: "sausage",
79
+ event_properties: { "a" => "b" },
80
+ user_properties: { "c" => "d" },
79
81
  time: time,
80
- ip: '127.0.0.1',
81
- platform: 'Web',
82
- country: 'United States',
83
- insert_id: 'bestId'
82
+ ip: "127.0.0.1",
83
+ platform: "Web",
84
+ country: "United States",
85
+ insert_id: "bestId"
84
86
  )
85
87
 
86
- expect(event.to_hash).to eq(event_type: 'sausage',
88
+ expect(event.to_hash).to eq(event_type: "sausage",
87
89
  user_id: 123,
88
- device_id: 'abcd',
89
- event_properties: { 'a' => 'b' },
90
- user_properties: { 'c' => 'd' },
90
+ device_id: "abcd",
91
+ event_properties: { "a" => "b" },
92
+ user_properties: { "c" => "d" },
91
93
  time: 1_451_606_400_000,
92
- ip: '127.0.0.1',
93
- platform: 'Web',
94
- country: 'United States',
95
- insert_id: 'bestId')
94
+ ip: "127.0.0.1",
95
+ platform: "Web",
96
+ country: "United States",
97
+ insert_id: "bestId")
96
98
  end
97
99
  end
98
100
 
99
- context 'the user does not send in a price' do
100
- it 'raises an error if the user sends in a product_id' do
101
+ context "the user sends a revenue_type or a product_id" do
102
+ it "raises an error if there is not a price neither a revenue" do
101
103
  expect do
102
104
  described_class.new(
103
105
  user_id: 123,
104
- event_type: 'bad event',
105
- product_id: 'hopscotch.4lyfe'
106
+ event_type: "bad event",
107
+ product_id: "hopscotch.4lyfe"
106
108
  )
107
- end.to raise_error(ArgumentError)
109
+ end.to raise_error ArgumentError, /You must provide a price or a revenue/
110
+
111
+ expect do
112
+ described_class.new(
113
+ user_id: 123,
114
+ event_type: "bad event",
115
+ revenue_type: "whatever"
116
+ )
117
+ end.to raise_error ArgumentError, /You must provide a price or a revenue/
108
118
  end
109
119
 
110
- it 'raises an error if the user sends in a revenue_type' do
120
+ it "does not raise an error if there is a price" do
111
121
  expect do
112
122
  described_class.new(
113
123
  user_id: 123,
114
- event_type: 'bad event',
115
- revenue_type: 'tax return'
124
+ event_type: "bad event",
125
+ product_id: "hopscotch.4lyfe",
126
+ price: 10.2
116
127
  )
117
- end.to raise_error(ArgumentError)
128
+ end.not_to raise_error
129
+
130
+ expect do
131
+ described_class.new(
132
+ user_id: 123,
133
+ event_type: "bad event",
134
+ revenue_type: "whatever",
135
+ price: 10.2
136
+ )
137
+ end.not_to raise_error
138
+ end
139
+
140
+ it "does not raise an error if there is a revenue" do
141
+ expect do
142
+ described_class.new(
143
+ user_id: 123,
144
+ event_type: "bad event",
145
+ product_id: "hopscotch.4lyfe",
146
+ revenue: 100.1
147
+ )
148
+ end.not_to raise_error
149
+
150
+ expect do
151
+ described_class.new(
152
+ user_id: 123,
153
+ event_type: "bad event",
154
+ revenue_type: "whatever",
155
+ revenue: 100.1
156
+ )
157
+ end.not_to raise_error
118
158
  end
119
159
  end
120
160
  end
121
161
 
122
- describe '#to_hash' do
123
- it 'includes the event type' do
162
+ describe "#to_hash" do
163
+ it "includes the event type" do
124
164
  event = described_class.new(
125
165
  user_id: 123,
126
- event_type: 'clicked on home'
166
+ event_type: "clicked on home"
127
167
  )
128
- expect(event.to_hash[:event_type]).to eq('clicked on home')
168
+ expect(event.to_hash[:event_type]).to eq("clicked on home")
129
169
  end
130
170
 
131
- it 'includes arbitrary properties' do
171
+ it "includes arbitrary properties" do
132
172
  event = described_class.new(
133
173
  user_id: 123,
134
- event_type: 'clicked on home',
174
+ event_type: "clicked on home",
135
175
  event_properties: { abc: :def }
136
176
  )
137
177
  expect(event.to_hash[:event_properties]).to eq(abc: :def)
138
178
  end
139
179
 
140
- describe 'time' do
141
- it 'includes a time for the event' do
180
+ describe "time" do
181
+ it "includes a time for the event" do
142
182
  time = Time.at(1_451_606_400_000 / 1_000)
143
183
  event = described_class.new(
144
184
  user_id: 123,
145
- event_type: 'clicked on home',
185
+ event_type: "clicked on home",
146
186
  time: time
147
187
  )
148
188
  expect(event.to_hash[:time]).to eq(1_451_606_400_000)
149
189
  end
150
190
 
151
- it 'does not include time if it is not set' do
191
+ it "does not include time if it is not set" do
152
192
  event = described_class.new(
153
193
  user_id: 123,
154
- event_type: 'clicked on home'
194
+ event_type: "clicked on home"
155
195
  )
156
196
  expect(event.to_hash).not_to have_key(:time)
157
197
  end
158
198
  end
159
199
 
160
- describe 'insert_id' do
161
- it 'includes an insert_id for the event' do
200
+ describe "insert_id" do
201
+ it "includes an insert_id for the event" do
162
202
  event = described_class.new(
163
203
  user_id: 123,
164
- event_type: 'clicked on home',
165
- insert_id: 'foo-bar'
204
+ event_type: "clicked on home",
205
+ insert_id: "foo-bar"
166
206
  )
167
- expect(event.to_hash[:insert_id]).to eq('foo-bar')
207
+ expect(event.to_hash[:insert_id]).to eq("foo-bar")
168
208
  end
169
209
 
170
- it 'does not include insert_id if it is not set' do
210
+ it "does not include insert_id if it is not set" do
171
211
  event = described_class.new(
172
212
  user_id: 123,
173
- event_type: 'clicked on home'
213
+ event_type: "clicked on home"
174
214
  )
175
215
  expect(event.to_hash).not_to have_key(:insert_id)
176
216
  end
177
217
  end
178
218
 
179
- describe 'platform' do
180
- it 'includes the platform for the event' do
219
+ describe "platform" do
220
+ it "includes the platform for the event" do
181
221
  event = described_class.new(
182
222
  user_id: 123,
183
- event_type: 'clicked on home',
184
- platform: 'Web'
223
+ event_type: "clicked on home",
224
+ platform: "Web"
185
225
  )
186
- expect(event.to_hash[:platform]).to eq('Web')
226
+ expect(event.to_hash[:platform]).to eq("Web")
187
227
  end
188
228
 
189
- it 'does not include the platform if it is not set' do
229
+ it "does not include the platform if it is not set" do
190
230
  event = described_class.new(
191
231
  user_id: 123,
192
- event_type: 'clicked on home'
232
+ event_type: "clicked on home"
193
233
  )
194
234
  expect(event.to_hash).not_to have_key(:platform)
195
235
  end
196
236
  end
197
237
 
198
- describe 'country' do
199
- it 'includes the country for the event' do
238
+ describe "country" do
239
+ it "includes the country for the event" do
200
240
  event = described_class.new(
201
241
  user_id: 123,
202
- event_type: 'clicked on home',
203
- country: 'United States'
242
+ event_type: "clicked on home",
243
+ country: "United States"
204
244
  )
205
- expect(event.to_hash[:country]).to eq('United States')
245
+ expect(event.to_hash[:country]).to eq("United States")
206
246
  end
207
247
 
208
- it 'does not include the country if it is not set' do
248
+ it "does not include the country if it is not set" do
209
249
  event = described_class.new(
210
250
  user_id: 123,
211
- event_type: 'clicked on home'
251
+ event_type: "clicked on home"
212
252
  )
213
253
  expect(event.to_hash).not_to have_key(:country)
214
254
  end
215
255
  end
216
256
 
217
- describe 'revenue params' do
218
- it 'includes the price if it is set' do
257
+ describe "revenue params" do
258
+ it "includes the price if it is set" do
219
259
  price = 100_000.99
220
260
  event = described_class.new(
221
261
  user_id: 123,
222
- event_type: 'clicked on home',
262
+ event_type: "clicked on home",
223
263
  price: price
224
264
  )
225
265
  expect(event.to_hash[:price]).to eq(price)
226
266
  end
227
267
 
228
- it 'sets the quantity to 1 if the price is set and the quantity is not' do
229
- price = 100_000.99
268
+ it "includes the quantity if it is set" do
269
+ quantity = 100
230
270
  event = described_class.new(
231
271
  user_id: 123,
232
- event_type: 'clicked on home',
233
- price: price
272
+ event_type: "clicked on home",
273
+ quantity: quantity,
274
+ price: 10.99
234
275
  )
235
- expect(event.to_hash[:quantity]).to eq(1)
276
+ expect(event.to_hash[:quantity]).to eq(quantity)
236
277
  end
237
278
 
238
- it 'includes the quantity if it is set' do
239
- quantity = 100
279
+ it "includes the revenue if it is set" do
280
+ revenue = 100
240
281
  event = described_class.new(
241
282
  user_id: 123,
242
- event_type: 'clicked on home',
243
- quantity: quantity,
244
- price: 10.99
283
+ event_type: "clicked on home",
284
+ quantity: 456,
285
+ revenue: revenue
245
286
  )
246
- expect(event.to_hash[:quantity]).to eq(quantity)
287
+ expect(event.to_hash[:revenue]).to eq(revenue)
247
288
  end
248
289
 
249
- it 'includes the productID if set' do
250
- product_id = 'hopscotch.subscriptions.rule'
290
+ it "includes the productID if set" do
291
+ product_id = "hopscotch.subscriptions.rule"
251
292
  event = described_class.new(
252
293
  user_id: 123,
253
- event_type: 'clicked on home',
294
+ event_type: "clicked on home",
254
295
  price: 199.99,
255
296
  product_id: product_id
256
297
  )
257
298
  expect(event.to_hash[:productId]).to eq(product_id)
258
299
  end
259
300
 
260
- it 'includes the revenueType if set' do
261
- revenue_type = 'income'
301
+ it "includes the revenueType if set" do
302
+ revenue_type = "income"
262
303
  event = described_class.new(
263
304
  user_id: 123,
264
- event_type: 'clicked on home',
305
+ event_type: "clicked on home",
265
306
  price: 199.99,
266
307
  revenue_type: revenue_type
267
308
  )
268
309
  expect(event.to_hash[:revenueType]).to eq(revenue_type)
269
310
  end
270
311
 
271
- it 'does not include revenue params if they are not set' do
312
+ it "does not include revenue params if they are not set" do
272
313
  event = described_class.new(
273
314
  user_id: 123,
274
- event_type: 'clicked on home'
315
+ event_type: "clicked on home"
275
316
  )
276
317
  expect(event.to_hash).not_to have_key(:quantity)
277
318
  expect(event.to_hash).not_to have_key(:revenueType)
@@ -280,4 +321,44 @@ describe AmplitudeAPI::Event do
280
321
  end
281
322
  end
282
323
  end
324
+
325
+ describe "arbitrary properties" do
326
+ # We need to create a class for each test because the methods we are calling
327
+ # in this test group are modifying the class
328
+ let(:klass) { Class.new described_class }
329
+
330
+ let(:event) {
331
+ klass.new(
332
+ user_id: 123,
333
+ event_type: "bad event"
334
+ )
335
+ }
336
+
337
+ it "creates arbitrary properties when assigning values" do
338
+ event.arbitrary_property = "arbitrary value"
339
+
340
+ expect(event.arbitrary_property).to eq "arbitrary value"
341
+ end
342
+
343
+ it "responds_to? arbitrary properties" do
344
+ event.arbitrary_property = "arbitrary value"
345
+
346
+ expect(event.respond_to?(:arbitrary_property)).to be true
347
+ expect(event.respond_to?(:arbitrary_property=)).to be true
348
+ end
349
+
350
+ it "do not accepts blocks when assigning values to create properties" do
351
+ expect do
352
+ event.arbitrary_property { puts "whatever" }
353
+ end.to raise_error NoMethodError
354
+ end
355
+
356
+ it "includes arbitrary properties in the generated hash" do
357
+ event.arbitrary_property = "arbitrary value"
358
+
359
+ hash = event.to_hash
360
+
361
+ expect(hash).to include(arbitrary_property: "arbitrary value")
362
+ end
363
+ end
283
364
  end