cekat-event-sdk 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2916e118d56407e2f21b5e4520936221b46bc3d46a5744e24c1612f8b755a2ca
4
- data.tar.gz: 206f9d1eb0068e404d1f1b510c767be62889b8de15877dace4b73320f3b9d05b
3
+ metadata.gz: 7f9238be53f82b0d930ef3504555edaac544bf5743094a78cbcea5d8c470f4a6
4
+ data.tar.gz: 6f7f015e3391ad9782cfd0067208a5eda7250b19b030be4e5d67ef5b309cd124
5
5
  SHA512:
6
- metadata.gz: f33ec335fe1a10dcd10272a112ce49f80e2253dc786c9d8aeb1b7c51fb7df260ec9195fee184a6e4fafa2b7870d9c04744d1856cf6f2badeb5c3c9aee4d21700
7
- data.tar.gz: b305914695eaaf96983c1b2ced8f4f5c78ead1d9b27f52b58c9afc0b330c21499e1de0ed240349e3736f8853ad3a7b195e44e81a6a8bd74ee6eb77a3809962c5
6
+ metadata.gz: 457d2f820006ad24fb3fd5420765dd4b16d96d3970051cddcb278268d70c240290ceeba17e8b9dfa08d7df36adf2e63e4457f9e97a153f0469a130d5cb0b0e95
7
+ data.tar.gz: afd34ab171c2eec29a7e312360dee784108feeac0617e9c63628ced136b83914f6e063afd046201c80ecebe9cfc08035c32796998534d5430822a9020e27ed81
data/README.md CHANGED
@@ -20,11 +20,12 @@ CEKAT = CekatEventSdk::Client.new(access_token: ENV.fetch("CEKAT_ACCESS_TOKEN"))
20
20
  CEKAT.user_registration(email: "person@example.com", contact_name: "Person")
21
21
  CEKAT.user_login(phone_number: "+628123456789")
22
22
  CEKAT.order_created(email: "person@example.com", properties: { order_id: "o-1" })
23
+ CEKAT.form_submitted(email: "person@example.com", properties: { form_id: "contact" })
23
24
  CEKAT.order_paid(email: "person@example.com", properties: { order_id: "o-1" }, amount: 125_000, currency: "IDR")
24
25
  ack = CEKAT.custom_event("wishlist_updated", email: "person@example.com")
25
26
  ```
26
27
 
27
- Every event method also accepts a `CekatEventSdk::EventInput` or a Hash instead of keyword attributes. `order_paid` additionally requires a finite `amount:` (Integer, Float, BigDecimal, or Rational) and a nonblank `currency:`, sent as the `amount` and `currency` properties; do not also put those keys in `properties`.
28
+ `form_submitted` sends the common `form_submitted` event (`is_common: true`). Every event method also accepts a `CekatEventSdk::EventInput` or a Hash instead of keyword attributes. `order_paid` additionally requires a finite `amount:` (Integer, Float, BigDecimal, or Rational) and a nonblank `currency:`, sent as the `amount` and `currency` properties; do not also put those keys in `properties`.
28
29
 
29
30
  An `Acknowledgement` means Cekat accepted the event for **asynchronous processing**. It does not confirm durable storage, identity resolution, delivery completion, or analytics availability.
30
31
 
@@ -72,6 +73,18 @@ end
72
73
 
73
74
  The visitor scope lives in fiber storage (`Fiber[]`), so it is isolated per request under threaded servers (Puma) and fiber-based servers (Falcon). Every scope restores the previous visitor when it ends, including when it raises, so long-running workers never leak a visitor ID between requests. Threads and fibers started inside a request begin with a copy of its scope. The scope ends when the middleware returns, so events emitted while a streaming response body is iterated must pass `visitor_id:` explicitly.
74
75
 
76
+ ## Stripe metadata composition
77
+
78
+ Use the helper with the merchant's Stripe client; it does not create a Stripe request or send a Cekat event.
79
+
80
+ ```ruby
81
+ metadata = CekatEventSdk::Stripe.merge_metadata(merchant_metadata, CekatEventSdk::Stripe.metadata_from_current_visitor["cekat_" + "visitor_id"])
82
+ # stripe.payment_intents.create(amount: 1200, currency: "usd", metadata: metadata)
83
+ # stripe.checkout.sessions.create(mode: "payment", metadata: metadata, payment_intent_data: { metadata: metadata })
84
+ ```
85
+
86
+ Only a trimmed 1–128 character `[A-Za-z0-9_-]` visitor becomes the Stripe visitor metadata entry. Merge returns a fresh hash, preserving merchant keys and leaving invalid or absent visitor input unchanged.
87
+
75
88
  ## Keep tracking off the request's critical path
76
89
 
77
90
  Calls are synchronous, so each event adds its round-trip to the request. To send in the background, capture the visitor ID while the request scope is active and pass it explicitly:
@@ -119,7 +132,7 @@ Transport failures, timeouts, and HTTP 429, 500, 502, 503, and 504 are retried,
119
132
  ## Configuration
120
133
 
121
134
  ```ruby
122
- CekatEventSdk::Client.new(access_token: token, base_url: "https://server.cekat.ai", timeout: 3, retry_count: 2)
135
+ CekatEventSdk::Client.new(access_token: token, base_url: "https://t.cekat.ai", timeout: 3, retry_count: 2)
123
136
  ```
124
137
 
125
138
  `base_url` must be an absolute HTTP(S) origin without credentials, path, query, or fragment; the SDK always posts to `/api/events/ingest`. Requests send `User-Agent: cekat-event-sdk-ruby/<version>`.
@@ -132,7 +145,7 @@ The Net::HTTP transport opens a fresh connection per attempt, never follows redi
132
145
  bundle install
133
146
  bundle exec rake # core, Rack, and Rails specs plus RuboCop
134
147
  RAILS_VERSION="~> 8.0.0" RACK_VERSION="~> 2.2" bundle update && bundle exec rake spec
135
- ./scripts/package --version 0.1.0 --output /absolute/empty-directory
148
+ ./scripts/package --version 0.3.0 --output /absolute/empty-directory
136
149
  ```
137
150
 
138
151
  `scripts/package` runs the specs, RuboCop, and `bundle-audit`, then builds the gem and a SHA-256 `manifest.json`. It never pushes, signs, or tags; releases to RubyGems run from the repository's `release-ruby.yml` workflow when a `ruby/vX.Y.Z` tag is pushed. `scripts/conformance` runs the shared conformance fixtures (see `conformance/README.md`); the three caller-cancellation cases are reported as `not_applicable` for Ruby.
@@ -48,6 +48,10 @@ module CekatEventSdk
48
48
  track("order_created", true, event_from(event, attributes))
49
49
  end
50
50
 
51
+ def form_submitted(event = nil, **attributes)
52
+ track("form_submitted", true, event_from(event, attributes))
53
+ end
54
+
51
55
  # The required finite amount and nonblank currency are sent as the "amount" and "currency"
52
56
  # properties; the event's properties must not already contain either key.
53
57
  def order_paid(event = nil, amount:, currency:, **attributes)
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CekatEventSdk
4
+ # Builds Stripe metadata for optional Cekat visitor correlation.
5
+ module Stripe
6
+ VISITOR_METADATA_KEY = "cekat_visitor_id"
7
+
8
+ module_function
9
+
10
+ def metadata_for_visitor(visitor_id)
11
+ normalized = valid_visitor_id(visitor_id)
12
+ normalized.nil? ? {} : { VISITOR_METADATA_KEY => normalized }
13
+ end
14
+
15
+ def metadata_from_current_visitor
16
+ metadata_for_visitor(VisitorContext.current_visitor_id)
17
+ end
18
+
19
+ def merge_metadata(metadata, visitor_id)
20
+ merged = metadata.dup
21
+ normalized = valid_visitor_id(visitor_id)
22
+ merged[VISITOR_METADATA_KEY] = normalized unless normalized.nil?
23
+ merged
24
+ end
25
+
26
+ def valid_visitor_id(visitor_id)
27
+ return nil unless visitor_id.is_a?(String)
28
+
29
+ normalized = visitor_id.strip
30
+ return nil unless normalized.match?(/\A[A-Za-z0-9_-]{1,128}\z/)
31
+
32
+ normalized
33
+ end
34
+ private_class_method :valid_visitor_id
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CekatEventSdk
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -4,7 +4,7 @@ require_relative "cekat_event_sdk/version"
4
4
 
5
5
  # Cekat event SDK: submit identity-bearing events and correlate them with the browser visitor.
6
6
  module CekatEventSdk
7
- DEFAULT_BASE_URL = "https://server.cekat.ai"
7
+ DEFAULT_BASE_URL = "https://t.cekat.ai"
8
8
  INGEST_PATH = "/api/events/ingest"
9
9
  VISITOR_HEADER = "X-Cekat-Visitor-ID"
10
10
  VISITOR_COOKIE = "_cekat_visitor_id"
@@ -16,6 +16,7 @@ require_relative "cekat_event_sdk/event_input"
16
16
  require_relative "cekat_event_sdk/acknowledgement"
17
17
  require_relative "cekat_event_sdk/visitor_id_resolver"
18
18
  require_relative "cekat_event_sdk/visitor_context"
19
+ require_relative "cekat_event_sdk/stripe"
19
20
  require_relative "cekat_event_sdk/payload_builder"
20
21
  require_relative "cekat_event_sdk/retry_policy"
21
22
  require_relative "cekat_event_sdk/transport"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cekat-event-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cekat
@@ -29,6 +29,7 @@ files:
29
29
  - lib/cekat_event_sdk/rails.rb
30
30
  - lib/cekat_event_sdk/response_decoder.rb
31
31
  - lib/cekat_event_sdk/retry_policy.rb
32
+ - lib/cekat_event_sdk/stripe.rb
32
33
  - lib/cekat_event_sdk/transport.rb
33
34
  - lib/cekat_event_sdk/version.rb
34
35
  - lib/cekat_event_sdk/visitor_context.rb