lucid_intercom 0.4.2 → 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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -22
  3. data/lib/lucid_intercom/attributes.rb +10 -42
  4. data/lib/lucid_intercom/changed_plan_event.rb +31 -0
  5. data/lib/lucid_intercom/company_attributes.rb +21 -0
  6. data/lib/lucid_intercom/company_custom_attributes.rb +48 -0
  7. data/lib/lucid_intercom/config.rb +44 -0
  8. data/lib/lucid_intercom/convert.rb +32 -0
  9. data/lib/lucid_intercom/{errors/error.rb → error.rb} +0 -0
  10. data/lib/lucid_intercom/event.rb +77 -0
  11. data/lib/lucid_intercom/installed_event.rb +31 -0
  12. data/lib/lucid_intercom/post_request.rb +26 -0
  13. data/lib/lucid_intercom/render_snippet.rb +28 -24
  14. data/lib/lucid_intercom/response.rb +51 -0
  15. data/lib/lucid_intercom/send_event.rb +22 -60
  16. data/lib/lucid_intercom/snippet.html.erb +2 -14
  17. data/lib/lucid_intercom/uninstalled_event.rb +27 -0
  18. data/lib/lucid_intercom/update_user.rb +24 -54
  19. data/lib/lucid_intercom/user_attributes.rb +47 -0
  20. data/lib/lucid_intercom/version.rb +1 -1
  21. data/lib/lucid_intercom.rb +18 -6
  22. metadata +56 -16
  23. data/lib/lucid_intercom/attributes/base.rb +0 -63
  24. data/lib/lucid_intercom/attributes/company.rb +0 -22
  25. data/lib/lucid_intercom/attributes/custom.rb +0 -47
  26. data/lib/lucid_intercom/attributes/user.rb +0 -28
  27. data/lib/lucid_intercom/credentials.rb +0 -35
  28. data/lib/lucid_intercom/errors/missing_credentials_error.rb +0 -7
  29. data/lib/lucid_intercom/errors/request_error.rb +0 -17
  30. data/lib/lucid_intercom/errors.rb +0 -3
  31. data/lib/lucid_intercom/events/base.rb +0 -23
  32. data/lib/lucid_intercom/events/changed_plan.rb +0 -37
  33. data/lib/lucid_intercom/events/installed.rb +0 -37
  34. data/lib/lucid_intercom/events/uninstalled.rb +0 -33
  35. data/lib/lucid_intercom/events.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e093b7cbc34689c682b5f4f1d3fd4fdef7ac033c9cf0fba38b0404e54f50c9a8
4
- data.tar.gz: e08a13e91779a38d92d076bcfad7a7e6003ad5b3ea4de3086cfc0ca9432d162e
3
+ metadata.gz: 1a133b6b1ae95502c5f15501cd40ea84d155d7f703cccc56befe4a32500533d6
4
+ data.tar.gz: 4e0b268ce267c890be6bbf61fc52f8bfbca449d37a45ee68a1db8db25f5be494
5
5
  SHA512:
6
- metadata.gz: b02dbad3e5c7284f146b53f02e2bac8ed500edb95662ed5cfc1a709330b80db817c035973a451f2d9af7a58f3d62d2dcb33df4f1b1b04a188d71fb186ce90703
7
- data.tar.gz: e2de118f2b5767081d4f8bea3d75ec8e359644799f94e1542c69917d248d12635a3af5d0348ac1f98674242c90f992d33437ee7316ac07d3657e80d83d2e0c33
6
+ metadata.gz: 6b089504958e012d93ca00a847ced2243ee5c22fbe93e2395250898be6063726f5ba87d3b2a2fae48383a3214996e73fb4ccbbb9cd958d56a50cfaec1f898762
7
+ data.tar.gz: 470849470d05d34ed775f382af97866684559fd9e0c0fdb95fdad207729f74dc0f6169cf6a6c2916fe2341c61c13d1ec39e7918787866a1aec2916f476bf6e64
data/README.md CHANGED
@@ -14,7 +14,7 @@ Usage
14
14
 
15
15
  ### Configure the default API credentials
16
16
 
17
- LucidIntercom.credentials = LucidIntercom::Credentials.new(
17
+ LucidIntercom.config = LucidIntercom::Config.new(
18
18
  '...', # access_token
19
19
  '...', # secret
20
20
  '...', # app_id
@@ -23,13 +23,10 @@ Usage
23
23
 
24
24
  Here, ‘app_prefix’ is the snakecased app name, e.g. ‘smart_order_tags’
25
25
 
26
- Alternatively, a credentials object may optionally be passed as a
27
- keyword argument to any of the classes listed below.
28
-
29
26
 
30
27
  ### Render the browser snippet
31
28
 
32
- LucidIntercom::RenderSnippet.new(shop_attributes, app_attributes).()
29
+ LucidIntercom::RenderSnippet.new.(shopify_data, app_data)
33
30
 
34
31
  This returns an HTML string which you can use in your view layout.
35
32
 
@@ -40,12 +37,14 @@ See the source code for documentation of arguments.
40
37
 
41
38
  When a user installs/uninstalls the app, or changes their plan:
42
39
 
43
- LucidIntercom::Events::Installed.new(shop_attributes).(plan_name)
44
- LucidIntercom::Events::Uninstalled.new(shop_attributes).()
45
- LucidIntercom::Events::ChangedPlan.new(shop_attributes).(plan_name)
40
+ event = LucidIntercom::InstalledEvent.new(shopify_data, new_plan)
41
+ event = LucidIntercom::UninstalledEvent.new(shopify_data)
42
+ event = LucidIntercom::ChangedPlanEvent.new(shopify_data, new_plan)
43
+
44
+ LucidIntercom::SendEvent.new.(event)
46
45
 
47
- Note that the `shop_attributes` hash for uninstalled events cannot
48
- be read from the API (as the access token is invalid at this stage).
46
+ Note that the `shopify_data` hash for uninstalled events cannot be
47
+ read from the API (as the access token is invalid at this stage).
49
48
  You should use the data hash provided with Shopify’s ‘app/uninstalled’
50
49
  webhook instead.
51
50
 
@@ -61,16 +60,7 @@ For free apps, use ‘free’.
61
60
  For partner-friendly app installs, use ‘partner’.
62
61
 
63
62
 
64
- ### Send a custom event
65
-
66
- LucidIntercom::SendEvent.new(shop_attributes).(event_name, event_metadata)
67
-
68
- See the source code for documentation of arguments.
69
-
70
-
71
- ### Update a user
72
-
73
- LucidIntercom::UpdateUser.new(shop_attributes, app_attributes).()
63
+ ### Custom events
74
64
 
75
- When this is called, and the user did not previously exist, the
76
- user will be created.
65
+ To define a custom event, subclass `LucidIntercom::Event`. See the
66
+ source code for documentation.
@@ -1,57 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lucid_intercom/attributes/user'
4
- require 'lucid_intercom/attributes/company'
5
- require 'lucid_intercom/attributes/custom'
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/convert'
6
6
 
7
7
  module LucidIntercom
8
8
  class Attributes
9
- #
10
- # @see LucidIntercom::Attributes::Base#initialize
11
- #
12
- def initialize(*args)
13
- @args = args
14
- end
9
+ extend Dry::Initializer
15
10
 
16
- #
17
- # @return [Hash]
18
- #
19
- def user
20
- user_browser.reject { |k, _| k == :user_hash }
21
- end
11
+ # @return [Hash] shop attributes as returned by the Shopify API
12
+ param :shopify_data, reader: :private
22
13
 
23
14
  #
24
- # User attributes for browser (with 'user_hash').
25
- #
26
- # @return [Hash]
15
+ # @abstract
27
16
  #
28
- def user_browser
29
- User.new(*@args).()
30
- end
31
-
32
- #
33
- # @return [Hash]
34
- #
35
- def company
36
- Company.new(*@args).()
37
- end
38
-
39
- #
40
- # Company attributes for browser (expects 'id', not 'company_id').
41
- #
42
- # @return [Hash]
43
- #
44
- def company_browser
45
- company2 = company
46
- company2[:id] = company2.delete(:company_id)
47
- company2
48
- end
49
-
17
+ # @param convert [#call]
50
18
  #
51
19
  # @return [Hash]
52
20
  #
53
- def custom
54
- Custom.new(*@args).()
21
+ def to_h(convert: Convert.new)
22
+ convert.({})
55
23
  end
56
24
  end
57
25
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/event'
4
+
5
+ module LucidIntercom
6
+ class ChangedPlanEvent < Event
7
+ # @return [String, nil] e.g. 'free', or nil to unset
8
+ param :new_plan
9
+
10
+ event :changed_plan
11
+
12
+ #
13
+ # @return [Hash]
14
+ #
15
+ def event_metadata
16
+ {
17
+ company_id: company.to_h[:company_id],
18
+ new_plan: new_plan,
19
+ }
20
+ end
21
+
22
+ #
23
+ # @return [Hash]
24
+ #
25
+ def app_data
26
+ {
27
+ plan: new_plan,
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/attributes'
4
+
5
+ module LucidIntercom
6
+ class CompanyAttributes < Attributes
7
+ #
8
+ # @param browser [Boolean] format for browser snippet
9
+ # @param convert [#call]
10
+ #
11
+ # @return [Hash]
12
+ #
13
+ def to_h(browser: false, convert: Convert.new)
14
+ convert.({}.tap do |h|
15
+ h[browser ? :id : :company_id] = shopify_data['myshopify_domain']
16
+ h[:name] = shopify_data['name']
17
+ h[:plan] = shopify_data['plan_name']
18
+ end)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/attributes'
4
+ require 'lucid_intercom/config'
5
+
6
+ module LucidIntercom
7
+ class CompanyCustomAttributes < Attributes
8
+ # @return [Hash] app attributes (unprefixed)
9
+ param :app_data, reader: :private
10
+
11
+ #
12
+ # @param convert [#call]
13
+ #
14
+ # @return [Hash]
15
+ #
16
+ def to_h(convert: Convert.new)
17
+ convert.(shopify.merge(app))
18
+ end
19
+
20
+ #
21
+ # These attributes are prefixed with 'merchant_' to distinguish them from
22
+ # the Shopify intergration's 'shopify_' prefix.
23
+ #
24
+ # @return [Hash]
25
+ #
26
+ private def shopify
27
+ {
28
+ merchant_domain: shopify_data['domain'],
29
+ merchant_myshopify_domain: shopify_data['myshopify_domain'],
30
+ merchant_shop_owner: shopify_data['shop_owner'],
31
+ merchant_timezone: shopify_data['timezone'],
32
+ }
33
+ end
34
+
35
+ #
36
+ # Any app-specific attributes.
37
+ #
38
+ # @return [Hash]
39
+ #
40
+ private def app
41
+ prefix = LucidIntercom.app_prefix
42
+
43
+ app_data.each_with_object({}) do |(k, v), h|
44
+ h["#{prefix}_#{k}"] = v
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+ require 'forwardable'
5
+
6
+ require 'lucid_intercom/error'
7
+
8
+ module LucidIntercom
9
+ NotConfiguredError = Class.new(Error)
10
+
11
+ class << self
12
+ extend Forwardable
13
+
14
+ # TODO: *Config.dry_initializer.attributes (version 2.0.0+)
15
+ def_delegators :config, :access_token, :secret, :app_id, :app_prefix
16
+
17
+ # @param config [Config]
18
+ attr_writer :config
19
+
20
+ #
21
+ # @return [Config]
22
+ #
23
+ # @raise [NotConfiguredError] if config is unset
24
+ #
25
+ def config
26
+ raise LucidIntercom::NotConfiguredError unless @config
27
+
28
+ @config
29
+ end
30
+ end
31
+
32
+ class Config
33
+ extend Dry::Initializer
34
+
35
+ # @return [String]
36
+ param :access_token
37
+ # @return [String]
38
+ param :secret
39
+ # @return [String]
40
+ param :app_id
41
+ # @return [String] the snakecased app name, e.g. 'smart_order_tags'
42
+ param :app_prefix
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LucidIntercom
4
+ class Convert
5
+ #
6
+ # @param attributes [Hash]
7
+ #
8
+ # @return [Hash]
9
+ #
10
+ def call(attributes)
11
+ attributes.each_with_object({}) do |(k, obj), h|
12
+ h[k] = convert(obj)
13
+ end
14
+ end
15
+
16
+ #
17
+ # @param obj [Object]
18
+ #
19
+ # @return [Object] a valid Intercom type
20
+ #
21
+ private def convert(obj)
22
+ case obj
23
+ when Numeric, nil # nil to unset
24
+ obj
25
+ when Time
26
+ obj.to_i
27
+ else
28
+ obj.to_s
29
+ end
30
+ end
31
+ end
32
+ end
File without changes
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/company_attributes'
4
+ require 'lucid_intercom/company_custom_attributes'
5
+ require 'lucid_intercom/config'
6
+ require 'lucid_intercom/user_attributes'
7
+
8
+ module LucidIntercom
9
+ class Event
10
+ extend Dry::Initializer
11
+
12
+ # @return [Hash] shop attributes as returned by the Shopify API
13
+ param :shopify_data
14
+ # @return [CompanyAttributes]
15
+ option :company, default: proc { CompanyAttributes.new(shopify_data) }
16
+ # @return [CompanyCustomAttributes]
17
+ option :company_custom, default: proc { CompanyCustomAttributes.new(shopify_data, app_data) }
18
+ # @return [UserAttributes]
19
+ option :user, default: proc { UserAttributes.new(shopify_data) }
20
+
21
+ #
22
+ # Set the event name for the subclass.
23
+ #
24
+ # @param event_name [String, #to_s]
25
+ #
26
+ # @example
27
+ # event :changed_plan
28
+ #
29
+ def self.event(event_name)
30
+ define_method(:event_name) do
31
+ "#{LucidIntercom.app_prefix}_#{event_name}"
32
+ end
33
+ end
34
+
35
+ #
36
+ # @abstract
37
+ #
38
+ # @return [String]
39
+ #
40
+ def event_name
41
+ raise NotImplementedError
42
+ end
43
+
44
+ #
45
+ # @abstract
46
+ #
47
+ # @return [Hash]
48
+ #
49
+ def event_metadata
50
+ raise NotImplementedError
51
+ end
52
+
53
+ #
54
+ # Additional custom attributes related to the event (unprefixed).
55
+ #
56
+ # @example
57
+ # {plan: 'free'}
58
+ #
59
+ # @example
60
+ # {plan: nil}
61
+ #
62
+ # @return [Hash]
63
+ #
64
+ def app_data
65
+ {}
66
+ end
67
+
68
+ #
69
+ # @return [Hash]
70
+ #
71
+ def user_id
72
+ {
73
+ user.id_key => user.id,
74
+ }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid_intercom/event'
4
+
5
+ module LucidIntercom
6
+ class InstalledEvent < Event
7
+ # @return [String] e.g. 'free'
8
+ param :new_plan
9
+
10
+ event :installed
11
+
12
+ #
13
+ # @return [Hash]
14
+ #
15
+ def event_metadata
16
+ {
17
+ company_id: company.to_h[:company_id],
18
+ new_plan: new_plan,
19
+ }
20
+ end
21
+
22
+ #
23
+ # @return [Hash]
24
+ #
25
+ def app_data
26
+ {
27
+ plan: new_plan,
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'http'
4
+
5
+ require 'lucid_intercom/config'
6
+ require 'lucid_intercom/response'
7
+
8
+ module LucidIntercom
9
+ class PostRequest
10
+ #
11
+ # @param path [String] path relative to the domain
12
+ # @param data [Hash]
13
+ #
14
+ # @return [Response]
15
+ #
16
+ def call(path, data)
17
+ res = HTTP.headers(
18
+ 'Authorization' => "Bearer #{LucidIntercom.access_token}",
19
+ 'Accept' => 'application/json',
20
+ 'Content-Type' => 'application/json'
21
+ ).post("https://api.intercom.io/#{path}", json: data)
22
+
23
+ Response.new(res.code)
24
+ end
25
+ end
26
+ end
@@ -1,46 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'erb'
4
- require 'lucid_intercom/attributes'
5
- require 'lucid_intercom/credentials'
4
+
5
+ require 'lucid_intercom/config'
6
6
 
7
7
  module LucidIntercom
8
8
  class RenderSnippet
9
9
  TEMPLATE = ERB.new(File.read("#{__dir__}/snippet.html.erb")).freeze
10
10
 
11
11
  #
12
- # Leave arguments unset for unauthenticated visitors.
13
- #
14
- # @param credentials [LucidIntercom::Credentials]
12
+ # @param shopify_data [Hash] shop attributes as returned by the Shopify API
13
+ # @param app_data [Hash] app attributes (unprefixed)
15
14
  #
16
- # @see LucidIntercom::Attributes#initialize
15
+ # @example Unauthenticated visitor
16
+ # render_snippet.()
17
17
  #
18
- def initialize(shop_attributes = {}, app_attributes = {}, credentials = LucidIntercom.credentials)
19
- @credentials = credentials
20
- @attributes = Attributes.new(shop_attributes, app_attributes, credentials) if shop_attributes.empty?
21
- end
22
-
23
- # @return [LucidIntercom::Attributes]
24
- attr_reader :attributes
25
- # @return [LucidIntercom::Credentials]
26
- attr_reader :credentials
27
-
18
+ # @example
19
+ # render_snippet.(shopify_data, app_data)
28
20
  #
29
- # @return [String] the rendered HTML
21
+ # @return [String]
30
22
  #
31
- def call
23
+ def call(shopify_data = {}, app_data = {})
24
+ company = CompanyAttributes.new(shopify_data).to_h(browser: true)
25
+ company_custom = CompanyCustomAttributes.new(shopify_data, app_data).to_h
26
+ user = UserAttributes.new(shopify_data).to_h(browser: true)
27
+
32
28
  TEMPLATE.result(binding)
33
29
  end
34
30
 
35
31
  #
36
- # Quote and escape a value for the window.intercomSettings object.
32
+ # Quote and escape a value for JavaScript.
37
33
  #
38
- private def h(v)
39
- v.is_a?(String) ? ?" + v.gsub(/./) { |c| escape_char(c) } + ?" : v
40
- end
34
+ # @param obj [Object]
35
+ #
36
+ # @return [Object]
37
+ #
38
+ def escape(obj)
39
+ return obj unless obj.is_a?(String)
40
+
41
+ s = obj.gsub(/./) do |c|
42
+ return c unless %w(" ' / < > \\).include?(c)
43
+
44
+ "\\#{c}"
45
+ end
41
46
 
42
- private def escape_char(c)
43
- %w(" ' / < > \\).include?(c) ? '\%s' % c : c
47
+ "\"#{s}\""
44
48
  end
45
49
  end
46
50
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/error'
6
+
7
+ module LucidIntercom
8
+ class Response
9
+ #
10
+ # @abstract
11
+ #
12
+ class Error < LucidIntercom::Error
13
+ extend Dry::Initializer
14
+
15
+ # @return [Integer]
16
+ param :status_code
17
+
18
+ #
19
+ # @return [String]
20
+ #
21
+ def message
22
+ "bad response (#{status_code})"
23
+ end
24
+ end
25
+
26
+ ClientError = Class.new(Error)
27
+ ServerError = Class.new(Error)
28
+
29
+ extend Dry::Initializer
30
+
31
+ # @return [Integer]
32
+ param :status_code
33
+
34
+ #
35
+ # @return [Boolean]
36
+ #
37
+ # @raise [ClientError] for status 4xx
38
+ # @raise [ServerError] for status 5xx
39
+ #
40
+ def assert!
41
+ case status_code
42
+ when 400..499
43
+ raise ClientError.new(status_code)
44
+ when 500..599
45
+ raise ServerError.new(status_code)
46
+ end
47
+
48
+ true
49
+ end
50
+ end
51
+ end
@@ -1,80 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require 'net/http'
5
- require 'uri'
6
- require 'lucid_intercom/attributes'
7
- require 'lucid_intercom/credentials'
8
- require 'lucid_intercom/errors'
3
+ require 'dry-initializer'
4
+
5
+ require 'lucid_intercom/post_request'
9
6
 
10
7
  module LucidIntercom
11
8
  class SendEvent
12
- #
13
- # @param shop_attributes [Hash] shop attributes in format returned by the Shopify API
14
- # @param credentials [LucidIntercom::Credentials]
15
- #
16
- def initialize(shop_attributes, credentials = LucidIntercom.credentials)
17
- @attributes = Attributes.new(shop_attributes, {}, credentials)
18
- @credentials = credentials
19
- end
20
-
21
- # @return [LucidIntercom::Attributes]
22
- attr_reader :attributes
23
- # @return [LucidIntercom::Credentials]
24
- attr_reader :credentials
25
-
26
- #
27
- # Send event for user identified by attributes.
28
- #
29
- # @param event_name [String]
30
- # @param event_metadata [Hash]
31
- #
32
- # @raise [LucidIntercom::RequestError] if the response status >= 400
33
- #
34
- def call(event_name, event_metadata)
35
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
36
- http.request(req, data(event_name, event_metadata))
37
- end
9
+ extend Dry::Initializer
38
10
 
39
- status = res.code.to_i
40
-
41
- if status >= 400 # rubocop:disable Style/GuardClause
42
- raise LucidIntercom::RequestError.new(status), 'invalid response code %s' % status
43
- end
44
- end
11
+ # @return [PostRequest]
12
+ option :post_request, default: proc { PostRequest.new }
13
+ # @return [UpdateUser]
14
+ option :update_user, default: proc { UpdateUser.new }
45
15
 
46
16
  #
47
- # @return [URI::HTTPS]
17
+ # @param event [Events::Event]
48
18
  #
49
- private def uri
50
- URI('https://api.intercom.io/events')
51
- end
52
-
19
+ # @raise [Response::ClientError] for status 4xx
20
+ # @raise [Response::ServerError] for status 5xx
53
21
  #
54
- # @return [Net::HTTP::Post]
55
- #
56
- private def req
57
- req = Net::HTTP::Post.new(uri)
58
- req['Authorization'] = "Bearer #{credentials.access_token}"
59
- req['Content-Type'] = 'application/json'
22
+ def call(event)
23
+ post_request.('events', data(event)).assert!
60
24
 
61
- req
25
+ update_user.(event)
62
26
  end
63
27
 
64
28
  #
65
- # @param event_name [String]
66
- # @param event_metadata [Hash]
29
+ # @param event [Events::Event]
67
30
  #
68
31
  # @return [Hash]
69
32
  #
70
- private def data(event_name, event_metadata)
71
- event = {}
72
- event[:email] = attributes.user[:email]
73
- event[:event_name] = event_name
74
- event[:created_at] = Time.now.utc.to_i
75
- event[:metadata] = event_metadata
76
-
77
- event.to_json
33
+ private def data(event)
34
+ {
35
+ **event.user_id,
36
+ event_name: event.event_name,
37
+ created_at: Time.now.utc.to_i,
38
+ metadata: event.event_metadata,
39
+ }
78
40
  end
79
41
  end
80
42
  end