plausible_api 0.1.3 → 0.1.5

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: 61ec37015a39b48b8ef1a5ff88f98452a87c590232ee527f03591d9fe3928a8d
4
- data.tar.gz: d8a7df06ccea331230058b18a900b41c850a55ca18d9e850d1cc2fbf7fa7bbcc
3
+ metadata.gz: 22016ef4c32d7f1d0470a619111b0134134e3c272ed62a6630f3f81184e7cd50
4
+ data.tar.gz: ef9f7efae941960ca78dca62b4b5f02207ddfb6ebeffb174120edcc0c14b7eec
5
5
  SHA512:
6
- metadata.gz: a0ce1d1dc380b44136fc38f193e307ee7b84872e6835043c02ebe89497c702daaf404efafe855c9b11f867569c612fe260ac0f1c79c959b30359d39df192d08c
7
- data.tar.gz: 0b28a11d857c1b2a9b83f5336fc833abb722e9492d602172f829c0bb12956c9aba7c426649ed01428a65f88d4c49ea421d44b09a808c639aa43c83b8453f8ada
6
+ metadata.gz: dfa7ec056c52894e489838410ec922d90544e80dca6525718c5c8629fa9fb9faece1fb76dd28f0fc8c6f455187ab46d5bd00e5d60ad7f7a8458c38e77ef60a5e
7
+ data.tar.gz: c858040b75e37e69c5d50813b78cf1ccf6708d24982ad865727adeb1a501839ed3b2a0244e8128fb99919dc97b41176c78bf870b1130be332bbfd07b27ee49bc
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plausible_api (0.1.3)
4
+ plausible_api (0.1.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -27,6 +27,7 @@ c.aggregate
27
27
  c.aggregate({ period: '30d' })
28
28
  c.aggregate({ period: '30d', metrics: 'visitors,pageviews' })
29
29
  c.aggregate({ period: '30d', metrics: 'visitors,pageviews', filters: 'event:page==/order/confirmation' })
30
+ c.aggregate({ period: 'custom', date: '2021-01-01,2021-02-10' })
30
31
 
31
32
  # You'll get something like this:
32
33
  => {"bounce_rate"=>{"value"=>81.0}, "pageviews"=>{"value"=>29}, "visit_duration"=>{"value"=>247.0}, "visitors"=>{"value"=>14}}
@@ -42,11 +43,27 @@ c.timeseries
42
43
  # Set parameters (period, filters, interval)
43
44
  c.timeseries({ period: '7d' })
44
45
  c.timeseries({ period: '7d', filters: 'event:page==/order/confirmation' })
46
+ c.timeseries({ period: 'custom', date: '2021-01-01,2021-02-15' })
45
47
 
46
48
  # You'll get something like this:
47
49
  => [{"date"=>"2021-01-11", "value"=>100}, {"date"=>"2021-01-12", "value"=>120}, {"date"=>"2021-01-13", "value"=>80}...]
48
50
  ```
49
51
 
52
+ ### Stats > Breakdown
53
+ ```rb
54
+ # Use the default parameters (30d, event:page)
55
+ c.breakdown
56
+
57
+ # Set parameters (property, period, metrics, limit, page, filters, date)
58
+ c.breakdown({ property: 'visit:source' })
59
+ c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews' })
60
+ c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews', period: '30d' })
61
+ c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews', period: 'custom', date: '2021-01-01,2021-02-01' })
62
+
63
+ # You'll get something like this:
64
+ => [{"page"=>"/", "visitors"=>41}, {"page"=>"/plans/", "visitors"=>14}, {"page"=>"/agencies/", "visitors"=>8}, {"page"=>"/features/", "visitors"=>8}, {"page"=>"/ready/", "visitors"=>5}, {"page"=>"/contact/", "visitors"=>4}, {"page"=>"/about/", "visitors"=>3}, {"page"=>"/donate/", "visitors"=>3}]
65
+ ```
66
+
50
67
  ### Realtime > Visitors
51
68
 
52
69
  It's as simple as:
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'plausible_api/stats/base'
3
4
  require 'plausible_api/stats/realtime/visitors'
4
5
  require 'plausible_api/stats/aggregate'
5
6
  require 'plausible_api/stats/timeseries'
7
+ require 'plausible_api/stats/breakdown'
6
8
 
7
9
  require 'json'
8
10
  require "net/http"
@@ -27,6 +29,10 @@ module PlausibleApi
27
29
  call PlausibleApi::Stats::Timeseries.new(options)
28
30
  end
29
31
 
32
+ def breakdown(options = {})
33
+ call PlausibleApi::Stats::Breakdown.new(options)
34
+ end
35
+
30
36
  def realtime_visitors
31
37
  call PlausibleApi::Stats::Realtime::Visitors.new
32
38
  end
@@ -37,6 +43,8 @@ module PlausibleApi
37
43
 
38
44
  private
39
45
  def call(api)
46
+ raise StandardError.new "There is some invalid parameters." unless api.valid?
47
+
40
48
  url = "#{BASE_URL}#{api.request_url.gsub('$SITE_ID', @site_id)}"
41
49
  uri = URI.parse(url)
42
50
 
@@ -46,7 +54,7 @@ module PlausibleApi
46
54
  http = Net::HTTP.new(uri.host, uri.port)
47
55
  http.use_ssl = true
48
56
 
49
- JSON.parse http.request(req).body
57
+ api.parse_response http.request(req).body
50
58
  end
51
59
  end
52
60
  end
@@ -2,21 +2,22 @@
2
2
 
3
3
  module PlausibleApi
4
4
  module Stats
5
- class Aggregate
5
+ class Aggregate < Base
6
6
  def initialize(options = {})
7
7
  @period = options[:period] || '30d'
8
8
  @metrics = options[:metrics] || 'visitors,pageviews,bounce_rate,visit_duration'
9
9
  @filters = options[:filters]
10
10
  @compare = options[:compare]
11
+ @date = options[:date]
12
+ @period = 'custom' if @date
11
13
  end
12
14
 
13
- def request_url
14
- url = "/api/v1/stats/aggregate?site_id=$SITE_ID"
15
- url += "&period=#{@period}" if @period
16
- url += "&metrics=#{@metrics}" if @metrics
17
- url += "&filters=#{CGI.escape(@filters)}" if @filters
18
- url += "&compare=#{@compare}" if @compare
19
- url
15
+ def request_url_base
16
+ "/api/v1/stats/aggregate?site_id=$SITE_ID"
17
+ end
18
+
19
+ def parse_response(body)
20
+ JSON.parse body
20
21
  end
21
22
  end
22
23
  end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlausibleApi
4
+ module Stats
5
+ class Base
6
+ def initialize(options = {})
7
+ raise NotImplementedError
8
+ end
9
+
10
+ def request_url_base
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def request_url
15
+ url = request_url_base
16
+ url += "&period=#{@period}" if defined?(@period) && @period
17
+ url += "&metrics=#{@metrics}" if defined?(@metrics) && @metrics
18
+ url += "&filters=#{CGI.escape(@filters)}" if defined?(@filters) && @filters
19
+ url += "&compare=#{@compare}" if defined?(@compare) && @compare
20
+ url += "&interval=#{@interval}" if defined?(@interval) && @interval
21
+ url += "&property=#{@property}" if defined?(@property) && @property
22
+ url += "&limit=#{@limit}" if defined?(@limit) && @limit
23
+ url += "&page=#{@page}" if defined?(@page) && @page
24
+ url += "&date=#{@date}" if defined?(@date) && @date
25
+ url
26
+ end
27
+
28
+ def parse_response(body)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def valid?
33
+ errors.empty?
34
+ end
35
+
36
+ def errors
37
+ allowed_period = %w(12mo 6mo month 30d 7d day custom)
38
+ allowed_metrics = %w(visitors pageviews bounce_rate visit_duration)
39
+ allowed_compare = %w(previous_period)
40
+ allowed_interval = %w(date month)
41
+ allowed_property = %w(event:page event:source event:referrer event:utm_medium
42
+ event:utm_source event:utm_campaign event:device event:browser event:browser_version
43
+ event:os event:os_version event:country)
44
+ e = 'Not a valid parameter. Allowed parameters are: '
45
+
46
+ errors = []
47
+ if defined?(@period) && @period
48
+ errors.push({ period: "#{e}#{allowed_period.join(', ')}" }) unless allowed_period.include? @period
49
+ end
50
+ if defined?(@metrics) && @metrics
51
+ metrics_array = @metrics.split(',')
52
+ errors.push({ metrics: "#{e}#{allowed_metrics.join(', ')}" }) unless metrics_array & allowed_metrics == metrics_array
53
+ end
54
+ if defined?(@compare) && @compare
55
+ errors.push({ compare: "#{e}#{allowed_compare.join(', ')}" }) unless allowed_compare.include? @compare
56
+ end
57
+ if defined?(@interval) && @interval
58
+ errors.push({ interval: "#{e}#{allowed_interval.join(', ')}" }) unless allowed_interval.include? @interval
59
+ end
60
+ if defined?(@property) && @property
61
+ errors.push({ property: "#{e}#{allowed_property.join(', ')}" }) unless allowed_property.include? @property
62
+ end
63
+ if defined?(@filters) && @filters
64
+ filters_array = @filters.to_s.split(';')
65
+ filters_array.each do |f|
66
+ parts = f.split("==")
67
+ errors.push({ filters: "Unrecognized filter: #{f}" }) unless parts.length == 2
68
+ errors.push({ filters: "Unknown metric for filter: #{parts[0]}" }) unless allowed_property.include? parts[0]
69
+ end
70
+ end
71
+ if defined?(@limit) && @limit
72
+ errors.push({ limit: "Limit param must be a positive number" }) unless @limit.is_a? Integer and @limit > 0
73
+ end
74
+ if defined?(@page) && @page
75
+ errors.push({ page: "Page param must be a positive number" }) unless @page.is_a? Integer and @page > 0
76
+ end
77
+ if defined?(@date) && @date
78
+ errors.push({ date: 'You must define the period parameter as custom' }) unless @period == 'custom'
79
+ date_array = @date.split(",")
80
+ errors.push({ date: 'You must define start and end dates divided by comma' }) unless date_array.length == 2
81
+ regex = /\d{4}\-\d{2}\-\d{2}/
82
+ errors.push({ date: 'Wrong format for the start date' }) unless date_array[0] =~ regex
83
+ errors.push({ date: 'Wrong format for the end date' }) unless date_array[1] =~ regex
84
+ end
85
+ errors
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlausibleApi
4
+ module Stats
5
+ class Breakdown < Base
6
+ def initialize(options = {})
7
+ @property = options[:property] || 'event:page' # required
8
+ @period = options[:period] || '30d' # required
9
+ @metrics = options[:metrics]
10
+ @limit = options[:limit]
11
+ @page = options[:page]
12
+ @filters = options[:filters]
13
+ @date = options[:date]
14
+ @period = 'custom' if @date
15
+
16
+ end
17
+
18
+ def request_url_base
19
+ "/api/v1/stats/breakdown?site_id=$SITE_ID"
20
+ end
21
+
22
+ def parse_response(body)
23
+ JSON.parse(body)['results']
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,13 +3,17 @@
3
3
  module PlausibleApi
4
4
  module Stats
5
5
  module Realtime
6
- class Visitors
6
+ class Visitors < PlausibleApi::Stats::Base
7
7
  def initialize
8
8
  end
9
9
 
10
- def request_url
10
+ def request_url_base
11
11
  "/api/v1/stats/realtime/visitors?site_id=$SITE_ID"
12
12
  end
13
+
14
+ def parse_response(body)
15
+ body.to_i
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -2,19 +2,21 @@
2
2
 
3
3
  module PlausibleApi
4
4
  module Stats
5
- class Timeseries
5
+ class Timeseries < Base
6
6
  def initialize(options = {})
7
7
  @period = options[:period] || '30d'
8
8
  @filters = options[:filters]
9
9
  @interval = options[:interval]
10
+ @date = options[:date]
11
+ @period = 'custom' if @date
10
12
  end
11
13
 
12
- def request_url
13
- url = "/api/v1/stats/timeseries?site_id=$SITE_ID"
14
- url += "&period=#{@period}" if @period
15
- url += "&filters=#{CGI.escape(@filters)}" if @filters
16
- url += "&interval=#{@interval}" if @interval
17
- url
14
+ def request_url_base
15
+ "/api/v1/stats/timeseries?site_id=$SITE_ID"
16
+ end
17
+
18
+ def parse_response(body)
19
+ JSON.parse(body)['results']
18
20
  end
19
21
  end
20
22
  end
@@ -1,3 +1,3 @@
1
1
  module PlausibleApi
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.5"
3
3
  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.3
4
+ version: 0.1.5
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-02-15 00:00:00.000000000 Z
11
+ date: 2021-02-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:
@@ -29,6 +29,8 @@ files:
29
29
  - lib/plausible_api.rb
30
30
  - lib/plausible_api/client.rb
31
31
  - lib/plausible_api/stats/aggregate.rb
32
+ - lib/plausible_api/stats/base.rb
33
+ - lib/plausible_api/stats/breakdown.rb
32
34
  - lib/plausible_api/stats/realtime/visitors.rb
33
35
  - lib/plausible_api/stats/timeseries.rb
34
36
  - lib/plausible_api/version.rb