plausible_api 0.1.10 → 0.3

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: 5fcd7e3adaeb1c8fb8dc1de67e305573708d04e971e995bcffeb4d0fe71ec8ff
4
- data.tar.gz: b729b5a5de1b5f6572c175879e77daed92aba1cc60075033b1e693752e13b7ce
3
+ metadata.gz: 3164447cd3eac3c7a7cbf0c7e7cccd36eaf2bd195966283fc0da4ad023b7b21e
4
+ data.tar.gz: 34acbb3e21f80bd3537d4273b6555dea0da7e4fdb5cf3dcbf8bede5d477e8ce0
5
5
  SHA512:
6
- metadata.gz: 0d0757ae94943225433757648bc542dd2afa2a1706696b35cdb179f7f117cb8a8b34581ea0bc7a50ac1d8973c137206bf520e2b6d27129d06c7ff310ca757d6e
7
- data.tar.gz: db68b71615cb9026ae5a9dddaa1fee92c51740d0314f556e032cd0975ea71675fbade8733e80c1b4975e53d64d7f1347747b10cb1a73b8f5c034d29b3f396590
6
+ metadata.gz: 03273d140652347b6b282d94ff0c6294746fc7bd410dcaa1feab54a627d80ed64fa8eb1c9c56c0a3a0e3e2a95cb9cda755501987f46a3b795cb9dc2862aa1e01
7
+ data.tar.gz: b6e84673b3763918a28488c717e3be089107571ecb1b357b4d7e2b1ded589b68eade9d65f615e70a6655b4571a73c7bf767a0af3363b6ca90631cd0810ea91e8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plausible_api (0.1.10)
4
+ plausible_api (0.3)
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,31 @@ 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
+ ```
89
+
90
+
91
+ ### Self-hosted Plausible instances
92
+
93
+ If you are using a self-hosted Plausible instance, you can set the `base_url` before initializing the client. On a Ruby on Rails app, you can add this to an initializer like `config/initializers/plausible.rb`
94
+
95
+ ```rb
96
+ # Do not include a trailing slash
97
+ PlausibleApi.configure do |config|
98
+ config.base_url = "https://your-plausible-instance.com"
99
+ end
100
+ ```
76
101
 
77
102
  ## Development
78
103
 
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,23 @@
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
-
19
18
  def initialize(site_id, token)
20
19
  @site_id = site_id.to_s
21
- @token = token.to_s
20
+ @token = token.to_s
22
21
  end
23
22
 
24
23
  def aggregate(options = {})
@@ -38,34 +37,42 @@ module PlausibleApi
38
37
  end
39
38
 
40
39
  def valid?
41
- begin
42
- realtime_visitors
43
- return true
44
- rescue
45
- return false
46
- end
40
+ realtime_visitors
41
+ true
42
+ rescue
43
+ false
44
+ end
45
+
46
+ def event(options = {})
47
+ call PlausibleApi::Event::Post.new(options.merge(domain: @site_id))
47
48
  end
48
49
 
49
50
  private
50
- def call(api)
51
- raise StandardError.new api.errors unless api.valid?
52
-
53
- url = "#{BASE_URL}#{api.request_url.gsub('$SITE_ID', @site_id)}"
51
+
52
+ SUCCESS_CODES = %w[200 202].freeze
53
+
54
+ def call(api)
55
+ raise Error, api.errors unless api.valid?
56
+ raise ConfigurationError, PlausibleApi.configuration.errors unless PlausibleApi.configuration.valid?
57
+
58
+ url = "#{PlausibleApi.configuration.base_url}#{api.request_url.gsub("$SITE_ID", @site_id)}"
54
59
  uri = URI.parse(url)
55
60
 
56
- req = Net::HTTP::Get.new(uri.request_uri)
57
- req.add_field('Authorization', "Bearer #{@token}")
61
+ req = api.request_class.new(uri.request_uri)
62
+ req.initialize_http_header(api.request_headers)
63
+ req.add_field("authorization", "Bearer #{@token}") if api.request_auth?
64
+ req.body = api.request_body if api.request_body?
58
65
 
59
66
  http = Net::HTTP.new(uri.host, uri.port)
60
- http.use_ssl = true
67
+ http.use_ssl = true
61
68
 
62
69
  response = http.request(req)
63
70
 
64
- if response.code == "200"
71
+ if SUCCESS_CODES.include?(response.code)
65
72
  api.parse_response response.body
66
73
  else
67
74
  raise StandardError.new response.body
68
75
  end
69
76
  end
70
77
  end
71
- end
78
+ end
@@ -0,0 +1,26 @@
1
+ module PlausibleApi
2
+ class Configuration
3
+ attr_accessor :base_url
4
+
5
+ # Setting up default values
6
+ def initialize
7
+ @base_url = "https://plausible.io"
8
+ end
9
+
10
+ def valid?
11
+ errors.empty?
12
+ end
13
+
14
+ def errors
15
+ errors = []
16
+ if base_url.nil? || base_url.empty?
17
+ errors.push(base_url: "base_url is required")
18
+ elsif !(URI.parse base_url).is_a? URI::HTTP
19
+ errors.push(base_url: "base_url is not a valid URL")
20
+ elsif base_url.end_with?("/")
21
+ errors.push(base_url: "base_url should not end with a trailing slash")
22
+ end
23
+ errors
24
+ end
25
+ end
26
+ 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
@@ -5,11 +5,11 @@ module PlausibleApi
5
5
  class Aggregate < Base
6
6
 
7
7
  def initialize(options = {})
8
- super({ period: '30d',
8
+ super({ period: '30d',
9
9
  metrics: 'visitors,visits,pageviews,views_per_visit,bounce_rate,visit_duration,events' }
10
10
  .merge(options))
11
11
  end
12
-
12
+
13
13
  def request_url_base
14
14
  "/api/v1/stats/aggregate?site_id=$SITE_ID"
15
15
  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
@@ -7,7 +7,7 @@ module PlausibleApi
7
7
  def initialize(options = {})
8
8
  super({ period: '30d', property: 'event:page' }.merge(options))
9
9
  end
10
-
10
+
11
11
  def request_url_base
12
12
  "/api/v1/stats/breakdown?site_id=$SITE_ID"
13
13
  end
@@ -17,4 +17,4 @@ module PlausibleApi
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -7,7 +7,7 @@ module PlausibleApi
7
7
  def initialize(options = {})
8
8
  super({ period: '30d' }.merge(options))
9
9
  end
10
-
10
+
11
11
  def request_url_base
12
12
  "/api/v1/stats/timeseries?site_id=$SITE_ID"
13
13
  end
@@ -17,4 +17,4 @@ module PlausibleApi
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module PlausibleApi
2
- VERSION = "0.1.10"
2
+ VERSION = "0.3"
3
3
  end
data/lib/plausible_api.rb CHANGED
@@ -1,7 +1,20 @@
1
- require 'plausible_api/version'
2
- require 'plausible_api/client'
1
+ require "plausible_api/version"
2
+ require "plausible_api/client"
3
+ require "plausible_api/configuration"
3
4
 
4
5
  module PlausibleApi
5
6
  class Error < StandardError; end
7
+
8
+ class ConfigurationError < StandardError; end
9
+
6
10
  # Your code goes here...
11
+ class << self
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+ end
7
20
  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.10
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gustavo Garcia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-14 00:00:00.000000000 Z
11
+ date: 2024-02-02 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,13 @@ 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/configuration.rb
34
+ - lib/plausible_api/event/base.rb
35
+ - lib/plausible_api/event/post.rb
31
36
  - lib/plausible_api/stats/aggregate.rb
32
37
  - lib/plausible_api/stats/base.rb
33
38
  - lib/plausible_api/stats/breakdown.rb