plausible_api 0.1.9 → 0.2

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: 946cc54d639da26e6d4e835df896ed3aa2237e9abf9c184085c28c7eafff0497
4
- data.tar.gz: c98ccc5b1060614edc3141282589fa5158d1367544699efadb89c5ff9aecb0f0
3
+ metadata.gz: 77c960fb14e022fa7f1ae47a7c38903325d188d98c67ac598977812326b616be
4
+ data.tar.gz: 4d0ed7d883293c49bfb518d544efbad968b544d249cb0bfc05ff5366c87a325e
5
5
  SHA512:
6
- metadata.gz: 9ce81d99cd4cce297c3cd388af7836e7f1415d6b5a04e83e51da7e44ba3bb042c8a97e7f9c059e1f1c69ad688e306c9cb98ed6c360e6afe26b908075a52e0063
7
- data.tar.gz: 21f54c76bd3a314748258681f34604e93928c257e663ff0f5df33bad13b5d5189feb9ecad6b1360e276160ad4dd11aa1e91c825ea2e2b8105827a6a63dbfdb17
6
+ metadata.gz: 6247be2a8f503c75bbff787771f1189598426171275122b6dddcc6581354db6ea3e2f81dd5c0ccc247c92ab7587f5f00c32ccc3d83b050ab70ff1470866bbbcb
7
+ data.tar.gz: 395a7b263fcfb9ce374f7e2d734a3d2ed608fd11755c4a6087fabc89a299da084fe5411063707e7066371660c1784ca2fa900d434d0daaefe8f00c398974dd7e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plausible_api (0.1.9)
4
+ plausible_api (0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -9,7 +9,7 @@ gem 'plausible_api'
9
9
  ```
10
10
  Then you need to initialize a Client with your `site_id` (the domain) and your `token`.
11
11
  ```rb
12
- c = PlausibleApi::Client.new('dailytics.com', '123123')
12
+ c = PlausibleApi::Client.new('dailytics.com', '123123')
13
13
 
14
14
  # Test if the site and token are valid
15
15
  c.valid?
@@ -73,6 +73,19 @@ c.realtime_visitors
73
73
  => 13
74
74
  ```
75
75
 
76
+ ### Events
77
+
78
+ You can send an event like this:
79
+
80
+ ```rb
81
+ # Example using Rack::Request in Rails for user_agent and ip.
82
+ c.event({
83
+ name: "signup",
84
+ url: 'https://dailytics.com/users/new',
85
+ user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.3",
86
+ ip: "127.0.0.1"
87
+ })
88
+ ```
76
89
 
77
90
  ## Development
78
91
 
data/examples/basic.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/setup'
2
+ require 'plausible_api'
3
+
4
+ client = PlausibleApi::Client.new(ENV["SITE_ID"], ENV["TOKEN"])
5
+ p client.valid?
data/examples/event.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler/setup'
2
+ require 'plausible_api'
3
+
4
+ client = PlausibleApi::Client.new(ENV["SITE_ID"], ENV["TOKEN"])
5
+
6
+ # default all the things, pointless but works
7
+ p client.event
8
+
9
+ # change the name
10
+ p client.event(
11
+ name: "test",
12
+ )
13
+
14
+ # send the whole kitchen sink
15
+ p client.event(
16
+ ip: "127.0.0.1",
17
+ user_agent: "test",
18
+ name: "test",
19
+ url: "app://localhost/test",
20
+ referrer: "https://example.com",
21
+ revenue: {currency: "USD", amount: 1.00},
22
+ props: {foo: "bar"},
23
+ )
@@ -1,24 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'plausible_api/stats/base'
4
- require 'plausible_api/stats/realtime/visitors'
5
- require 'plausible_api/stats/aggregate'
6
- require 'plausible_api/stats/timeseries'
7
- require 'plausible_api/stats/breakdown'
3
+ require "plausible_api/stats/base"
4
+ require "plausible_api/stats/realtime/visitors"
5
+ require "plausible_api/stats/aggregate"
6
+ require "plausible_api/stats/timeseries"
7
+ require "plausible_api/stats/breakdown"
8
+ require "plausible_api/event/base"
9
+ require "plausible_api/event/post"
8
10
 
9
- require 'json'
11
+ require "json"
10
12
  require "net/http"
11
13
  require "uri"
12
14
  require "cgi"
13
15
 
14
16
  module PlausibleApi
15
17
  class Client
16
-
17
- BASE_URL = 'https://plausible.io'
18
+ BASE_URL = "https://plausible.io"
18
19
 
19
20
  def initialize(site_id, token)
20
21
  @site_id = site_id.to_s
21
- @token = token.to_s
22
+ @token = token.to_s
22
23
  end
23
24
 
24
25
  def aggregate(options = {})
@@ -38,34 +39,41 @@ module PlausibleApi
38
39
  end
39
40
 
40
41
  def valid?
41
- begin
42
- realtime_visitors
43
- return true
44
- rescue
45
- return false
46
- end
42
+ realtime_visitors
43
+ true
44
+ rescue
45
+ false
46
+ end
47
+
48
+ def event(options = {})
49
+ call PlausibleApi::Event::Post.new(options.merge(domain: @site_id))
47
50
  end
48
51
 
49
52
  private
50
- def call(api)
53
+
54
+ SUCCESS_CODES = %w[200 202].freeze
55
+
56
+ def call(api)
51
57
  raise StandardError.new api.errors unless api.valid?
52
-
53
- url = "#{BASE_URL}#{api.request_url.gsub('$SITE_ID', @site_id)}"
58
+
59
+ url = "#{BASE_URL}#{api.request_url.gsub("$SITE_ID", @site_id)}"
54
60
  uri = URI.parse(url)
55
61
 
56
- req = Net::HTTP::Get.new(uri.request_uri)
57
- req.add_field('Authorization', "Bearer #{@token}")
62
+ req = api.request_class.new(uri.request_uri)
63
+ req.initialize_http_header(api.request_headers)
64
+ req.add_field("authorization", "Bearer #{@token}") if api.request_auth?
65
+ req.body = api.request_body if api.request_body?
58
66
 
59
67
  http = Net::HTTP.new(uri.host, uri.port)
60
- http.use_ssl = true
68
+ http.use_ssl = true
61
69
 
62
70
  response = http.request(req)
63
71
 
64
- if response.code == "200"
72
+ if SUCCESS_CODES.include?(response.code)
65
73
  api.parse_response response.body
66
74
  else
67
75
  raise StandardError.new response.body
68
76
  end
69
77
  end
70
78
  end
71
- end
79
+ end
@@ -0,0 +1,31 @@
1
+ module PlausibleApi
2
+ module Event
3
+ class Base
4
+ DEFAULT_USER_AGENT = "plausible_api_ruby/#{PlausibleApi::VERSION}"
5
+
6
+ def request_class
7
+ Net::HTTP::Post
8
+ end
9
+
10
+ def request_url_base
11
+ "/api/event"
12
+ end
13
+
14
+ def request_url
15
+ request_url_base
16
+ end
17
+
18
+ def request_auth?
19
+ false
20
+ end
21
+
22
+ def request_body?
23
+ true
24
+ end
25
+
26
+ def valid?
27
+ errors.empty?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlausibleApi
4
+ module Event
5
+ class Post < Base
6
+ DEFAULT_USER_AGENT = "plausible_api_ruby/#{PlausibleApi::VERSION}"
7
+ VALID_REVENUE_KEYS = %i[amount currency].freeze
8
+ OPTIONS_IN_HEADERS = %i[ip user_agent].freeze
9
+
10
+ attr_reader :domain
11
+ attr_reader :ip, :user_agent, :url
12
+ attr_reader :name, :props, :referrer, :revenue
13
+
14
+ def initialize(options = {})
15
+ @options = options.transform_keys(&:to_sym)
16
+
17
+ @domain = @options[:domain]
18
+ @ip = @options[:ip]
19
+ @user_agent = presence(@options[:user_agent]) || DEFAULT_USER_AGENT
20
+ @name = presence(@options[:name]) || "pageview"
21
+ @url = presence(@options[:url]) || "app://localhost/#{@name}"
22
+ @referrer = @options[:referrer]
23
+ @revenue = @options[:revenue]
24
+ @props = @options[:props]
25
+ end
26
+
27
+ def request_body
28
+ data = {
29
+ url: @url,
30
+ name: @name,
31
+ domain: @domain
32
+ }
33
+
34
+ data[:props] = @props if present?(@props)
35
+ data[:revenue] = @revenue if present?(@revenue)
36
+ data[:referrer] = @referrer if present?(@referrer)
37
+
38
+ JSON.generate(data)
39
+ end
40
+
41
+ def request_headers
42
+ headers = {
43
+ "content-type" => "application/json",
44
+ "user-agent" => @user_agent
45
+ }
46
+ headers["x-forwarded-for"] = @ip if present?(@ip)
47
+ headers
48
+ end
49
+
50
+ def parse_response(body)
51
+ body == "ok"
52
+ end
53
+
54
+ def errors
55
+ errors = []
56
+ errors.push(url: "url is required") if blank?(@url)
57
+ errors.push(name: "name is required") if blank?(@name)
58
+ errors.push(domain: "domain is required") if blank?(@domain)
59
+ errors.push(user_agent: "user_agent is required") if blank?(@user_agent)
60
+
61
+ if present?(@revenue)
62
+ if @revenue.is_a?(Hash)
63
+ unless valid_revenue_keys?(@revenue)
64
+ errors.push(
65
+ revenue: "revenue must have keys #{VALID_REVENUE_KEYS.join(", ")} " \
66
+ "but was #{@revenue.inspect}"
67
+ )
68
+ end
69
+ else
70
+ errors.push(revenue: "revenue must be a Hash")
71
+ end
72
+ end
73
+
74
+ if present?(@props) && !@props.is_a?(Hash)
75
+ errors.push(props: "props must be a Hash")
76
+ end
77
+
78
+ errors
79
+ end
80
+
81
+ private
82
+
83
+ def valid_revenue_keys?(revenue)
84
+ revenue.keys.sort.map(&:to_sym) == VALID_REVENUE_KEYS.sort
85
+ end
86
+
87
+ def present?(value)
88
+ !value.nil? && !value.empty?
89
+ end
90
+
91
+ def blank?(value)
92
+ !present?(value)
93
+ end
94
+
95
+ def presence(value)
96
+ return nil if blank?(value)
97
+ value
98
+ end
99
+ end
100
+ end
101
+ end
@@ -6,7 +6,7 @@ module PlausibleApi
6
6
 
7
7
  def initialize(options = {})
8
8
  super({ period: '30d',
9
- metrics: 'visitors,pageviews,bounce_rate,visit_duration' }
9
+ metrics: 'visitors,visits,pageviews,views_per_visit,bounce_rate,visit_duration,events' }
10
10
  .merge(options))
11
11
  end
12
12
 
@@ -19,4 +19,4 @@ module PlausibleApi
19
19
  end
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -15,11 +15,31 @@ module PlausibleApi
15
15
  raise NotImplementedError
16
16
  end
17
17
 
18
+ def request_class
19
+ Net::HTTP::Get
20
+ end
21
+
22
+ def request_body?
23
+ false
24
+ end
25
+
26
+ def request_body
27
+ nil
28
+ end
29
+
18
30
  def request_url
19
31
  params = @options.select{ |_,v| !v.to_s.empty? }
20
32
  [request_url_base, URI.encode_www_form(params)].reject{|e| e.empty?}.join('&')
21
33
  end
22
34
 
35
+ def request_headers
36
+ {}
37
+ end
38
+
39
+ def request_auth?
40
+ true
41
+ end
42
+
23
43
  def parse_response(body)
24
44
  raise NotImplementedError
25
45
  end
@@ -30,7 +50,7 @@ module PlausibleApi
30
50
 
31
51
  def errors
32
52
  allowed_period = %w(12mo 6mo month 30d 7d day custom)
33
- allowed_metrics = %w(visitors pageviews bounce_rate visit_duration)
53
+ allowed_metrics = %w(visitors visits pageviews views_per_visit bounce_rate visit_duration events)
34
54
  allowed_compare = %w(previous_period)
35
55
  allowed_interval = %w(date month)
36
56
  allowed_property = %w(event:page visit:entry_page visit:exit_page visit:source visit:referrer
@@ -1,3 +1,3 @@
1
1
  module PlausibleApi
2
- VERSION = "0.1.9"
2
+ VERSION = "0.2"
3
3
  end
data/lib/plausible_api.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'plausible_api/version'
2
- require 'plausible_api/client'
1
+ require "plausible_api/version"
2
+ require "plausible_api/client"
3
3
 
4
4
  module PlausibleApi
5
5
  class Error < StandardError; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plausible_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gustavo Garcia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-18 00:00:00.000000000 Z
11
+ date: 2023-12-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A very humble wrapper for the new API by Plausible
14
14
  email:
@@ -26,8 +26,12 @@ files:
26
26
  - Rakefile
27
27
  - bin/console
28
28
  - bin/setup
29
+ - examples/basic.rb
30
+ - examples/event.rb
29
31
  - lib/plausible_api.rb
30
32
  - lib/plausible_api/client.rb
33
+ - lib/plausible_api/event/base.rb
34
+ - lib/plausible_api/event/post.rb
31
35
  - lib/plausible_api/stats/aggregate.rb
32
36
  - lib/plausible_api/stats/base.rb
33
37
  - lib/plausible_api/stats/breakdown.rb
@@ -57,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
61
  - !ruby/object:Gem::Version
58
62
  version: '0'
59
63
  requirements: []
60
- rubygems_version: 3.1.4
64
+ rubygems_version: 3.3.7
61
65
  signing_key:
62
66
  specification_version: 4
63
67
  summary: A simple Plausible API wrapper for Rails