plausible_api 0.1.0 → 0.1.6
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 +4 -4
- data/Gemfile.lock +1 -9
- data/README.md +32 -9
- data/lib/plausible_api/client.rb +26 -8
- data/lib/plausible_api/stats/aggregate.rb +11 -20
- data/lib/plausible_api/stats/base.rb +84 -0
- data/lib/plausible_api/stats/breakdown.rb +20 -0
- data/lib/plausible_api/stats/realtime/visitors.rb +5 -4
- data/lib/plausible_api/stats/timeseries.rb +9 -16
- data/lib/plausible_api/version.rb +1 -1
- data/plausible_api.gemspec +0 -2
- metadata +5 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 040cbafdc8f270ac3f2bfdcaed7501535f801e93ba1059e6b776be42258714e9
|
4
|
+
data.tar.gz: 9e5511a3d7bb752a1b0a89e0f4d3b405eea5a6ca56262cf684626d7cf444dafc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83077cd7edeb80de8388afbea3fd85d2ba2e8068345e10df04331c6356f7dc5a7c7096da9774bfe2fa6324d76fd68ec5c80cf4c39f1dd499a39dbb8d73ba24c7
|
7
|
+
data.tar.gz: fc95a48bf881567cce4f126c899206e18cdfbbc0b0f3ddeba6e66f37553a12f2a77a541472005eafd3c07ddc435d70886fc95d13b751b906056d616bd5604a42
|
data/Gemfile.lock
CHANGED
@@ -1,21 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
plausible_api (0.1.
|
5
|
-
faraday (~> 1.0)
|
4
|
+
plausible_api (0.1.6)
|
6
5
|
|
7
6
|
GEM
|
8
7
|
remote: https://rubygems.org/
|
9
8
|
specs:
|
10
|
-
faraday (1.3.0)
|
11
|
-
faraday-net_http (~> 1.0)
|
12
|
-
multipart-post (>= 1.2, < 3)
|
13
|
-
ruby2_keywords
|
14
|
-
faraday-net_http (1.0.1)
|
15
9
|
minitest (5.14.3)
|
16
|
-
multipart-post (2.1.1)
|
17
10
|
rake (12.3.3)
|
18
|
-
ruby2_keywords (0.0.4)
|
19
11
|
|
20
12
|
PLATFORMS
|
21
13
|
ruby
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Plausible API
|
1
|
+
# Plausible API Ruby Gem
|
2
2
|
This is a simple wrapper to read the Plausible API with Ruby.
|
3
3
|
It's based on the WIP [API guide](https://plausible.io/docs/stats-api)
|
4
4
|
|
@@ -9,7 +9,11 @@ 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(
|
12
|
+
c = PlausibleApi::Client.new('dailytics.com', '123123')
|
13
|
+
|
14
|
+
# Test if the site and token are valid
|
15
|
+
c.valid?
|
16
|
+
=> true
|
13
17
|
```
|
14
18
|
|
15
19
|
### Stats > Aggregate
|
@@ -19,10 +23,11 @@ You have all these options to get the aggregate stats
|
|
19
23
|
# Use the default parameters (3mo period + the 4 main metrics)
|
20
24
|
c.aggregate
|
21
25
|
|
22
|
-
# Set parameters (period, metrics, filter,
|
26
|
+
# Set parameters (period, metrics, filter, compare)
|
23
27
|
c.aggregate({ period: '30d' })
|
24
28
|
c.aggregate({ period: '30d', metrics: 'visitors,pageviews' })
|
25
29
|
c.aggregate({ period: '30d', metrics: 'visitors,pageviews', filters: 'event:page==/order/confirmation' })
|
30
|
+
c.aggregate({ date: '2021-01-01,2021-02-10' })
|
26
31
|
|
27
32
|
# You'll get something like this:
|
28
33
|
=> {"bounce_rate"=>{"value"=>81.0}, "pageviews"=>{"value"=>29}, "visit_duration"=>{"value"=>247.0}, "visitors"=>{"value"=>14}}
|
@@ -35,19 +40,37 @@ You have all these options to get the timeseries
|
|
35
40
|
# Use the default parameters (3mo period)
|
36
41
|
c.timeseries
|
37
42
|
|
38
|
-
# Set parameters (period,
|
43
|
+
# Set parameters (period, filters, interval)
|
39
44
|
c.timeseries({ period: '7d' })
|
40
|
-
c.timeseries({ period: '7d', filters: 'event:page==/order/confirmation'
|
45
|
+
c.timeseries({ period: '7d', filters: 'event:page==/order/confirmation' })
|
46
|
+
c.timeseries({ date: '2021-01-01,2021-02-15' })
|
41
47
|
|
42
48
|
# You'll get something like this:
|
43
49
|
=> [{"date"=>"2021-01-11", "value"=>100}, {"date"=>"2021-01-12", "value"=>120}, {"date"=>"2021-01-13", "value"=>80}...]
|
44
50
|
```
|
45
51
|
|
46
|
-
###
|
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', 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
|
+
|
67
|
+
### Realtime > Visitors
|
47
68
|
|
48
|
-
|
69
|
+
It's as simple as:
|
49
70
|
```rb
|
50
71
|
c.realtime_visitors
|
72
|
+
|
73
|
+
=> 13
|
51
74
|
```
|
52
75
|
|
53
76
|
|
@@ -59,7 +82,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
59
82
|
|
60
83
|
## Contributing
|
61
84
|
|
62
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/dailytics/plausible_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/dailytics/plausible_api/blob/
|
85
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/dailytics/plausible_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/dailytics/plausible_api/blob/main/CODE_OF_CONDUCT.md).
|
63
86
|
|
64
87
|
|
65
88
|
## License
|
@@ -68,4 +91,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
68
91
|
|
69
92
|
## Code of Conduct
|
70
93
|
|
71
|
-
Everyone interacting in the PlausibleApi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/dailytics/plausible_api/blob/
|
94
|
+
Everyone interacting in the PlausibleApi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/dailytics/plausible_api/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/plausible_api/client.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
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
|
-
require 'faraday'
|
8
9
|
require 'json'
|
10
|
+
require "net/http"
|
11
|
+
require "uri"
|
12
|
+
require "cgi"
|
9
13
|
|
10
14
|
module PlausibleApi
|
11
15
|
class Client
|
12
16
|
|
13
17
|
BASE_URL = 'https://plausible.io'
|
14
18
|
|
15
|
-
def initialize(site_id
|
19
|
+
def initialize(site_id, token)
|
16
20
|
@site_id = site_id.to_s
|
17
21
|
@token = token.to_s
|
18
22
|
end
|
@@ -25,18 +29,32 @@ module PlausibleApi
|
|
25
29
|
call PlausibleApi::Stats::Timeseries.new(options)
|
26
30
|
end
|
27
31
|
|
32
|
+
def breakdown(options = {})
|
33
|
+
call PlausibleApi::Stats::Breakdown.new(options)
|
34
|
+
end
|
35
|
+
|
28
36
|
def realtime_visitors
|
29
37
|
call PlausibleApi::Stats::Realtime::Visitors.new
|
30
38
|
end
|
31
39
|
|
40
|
+
def valid?
|
41
|
+
realtime_visitors.is_a? Integer
|
42
|
+
end
|
43
|
+
|
32
44
|
private
|
33
|
-
def call(api)
|
45
|
+
def call(api)
|
46
|
+
raise StandardError.new "There is some invalid parameters." unless api.valid?
|
47
|
+
|
34
48
|
url = "#{BASE_URL}#{api.request_url.gsub('$SITE_ID', @site_id)}"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
49
|
+
uri = URI.parse(url)
|
50
|
+
|
51
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
52
|
+
req.add_field('Authorization', "Bearer #{@token}")
|
53
|
+
|
54
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
55
|
+
http.use_ssl = true
|
56
|
+
|
57
|
+
api.parse_response http.request(req).body
|
40
58
|
end
|
41
59
|
end
|
42
60
|
end
|
@@ -2,29 +2,20 @@
|
|
2
2
|
|
3
3
|
module PlausibleApi
|
4
4
|
module Stats
|
5
|
-
class Aggregate
|
5
|
+
class Aggregate < Base
|
6
|
+
|
6
7
|
def initialize(options = {})
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
super({ period: '30d',
|
9
|
+
metrics: 'visitors,pageviews,bounce_rate,visit_duration' }
|
10
|
+
.merge(options))
|
11
|
+
end
|
12
|
+
|
13
|
+
def request_url_base
|
14
|
+
"/api/v1/stats/aggregate?site_id=$SITE_ID"
|
11
15
|
end
|
12
16
|
|
13
|
-
def
|
14
|
-
|
15
|
-
if @period
|
16
|
-
url += "&period=#{@period}"
|
17
|
-
end
|
18
|
-
if @metrics
|
19
|
-
url += "&metrics=#{@metrics}"
|
20
|
-
end
|
21
|
-
if @filters
|
22
|
-
url += "&filters=#{CGI.escape(@filters)}"
|
23
|
-
end
|
24
|
-
if @date
|
25
|
-
url += "&date=#{@date}"
|
26
|
-
end
|
27
|
-
url
|
17
|
+
def parse_response(body)
|
18
|
+
JSON.parse body
|
28
19
|
end
|
29
20
|
end
|
30
21
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlausibleApi
|
4
|
+
module Stats
|
5
|
+
class Base
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@options = { compare: nil, date: nil, filters: nil, interval: nil,
|
9
|
+
limit: nil, metrics: nil, page: nil, period: nil,
|
10
|
+
property: nil }.merge(options)
|
11
|
+
@options[:period] = 'custom' if @options[:date]
|
12
|
+
end
|
13
|
+
|
14
|
+
def request_url_base
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_url
|
19
|
+
params = @options.select{ |_,v| !v.to_s.empty? }
|
20
|
+
[request_url_base, URI.encode_www_form(params)].reject{|e| e.empty?}.join('&')
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_response(body)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
errors.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def errors
|
32
|
+
allowed_period = %w(12mo 6mo month 30d 7d day custom)
|
33
|
+
allowed_metrics = %w(visitors pageviews bounce_rate visit_duration)
|
34
|
+
allowed_compare = %w(previous_period)
|
35
|
+
allowed_interval = %w(date month)
|
36
|
+
allowed_property = %w(event:page visit:source visit:referrer visit:utm_medium
|
37
|
+
visit:utm_source visit:utm_campaign visit:device visit:browser visit:browser_version
|
38
|
+
visit:os visit:os_version visit:country)
|
39
|
+
e = 'Not a valid parameter. Allowed parameters are: '
|
40
|
+
|
41
|
+
errors = []
|
42
|
+
if @options[:period]
|
43
|
+
errors.push({ period: "#{e}#{allowed_period.join(', ')}" }) unless allowed_period.include? @options[:period]
|
44
|
+
end
|
45
|
+
if @options[:metrics]
|
46
|
+
metrics_array = @options[:metrics].split(',')
|
47
|
+
errors.push({ metrics: "#{e}#{allowed_metrics.join(', ')}" }) unless metrics_array & allowed_metrics == metrics_array
|
48
|
+
end
|
49
|
+
if @options[:compare]
|
50
|
+
errors.push({ compare: "#{e}#{allowed_compare.join(', ')}" }) unless allowed_compare.include? @options[:compare]
|
51
|
+
end
|
52
|
+
if @options[:interval]
|
53
|
+
errors.push({ interval: "#{e}#{allowed_interval.join(', ')}" }) unless allowed_interval.include? @options[:interval]
|
54
|
+
end
|
55
|
+
if @options[:property]
|
56
|
+
errors.push({ property: "#{e}#{allowed_property.join(', ')}" }) unless allowed_property.include? @options[:property]
|
57
|
+
end
|
58
|
+
if @options[:filters]
|
59
|
+
filters_array = @options[:filters].to_s.split(';')
|
60
|
+
filters_array.each do |f|
|
61
|
+
parts = f.split("==")
|
62
|
+
errors.push({ filters: "Unrecognized filter: #{f}" }) unless parts.length == 2
|
63
|
+
errors.push({ filters: "Unknown metric for filter: #{parts[0]}" }) unless allowed_property.include? parts[0]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if @options[:limit]
|
67
|
+
errors.push({ limit: "Limit param must be a positive number" }) unless @options[:limit].is_a? Integer and @options[:limit] > 0
|
68
|
+
end
|
69
|
+
if @options[:page]
|
70
|
+
errors.push({ page: "Page param must be a positive number" }) unless @options[:page].is_a? Integer and @options[:page] > 0
|
71
|
+
end
|
72
|
+
if @options[:date]
|
73
|
+
errors.push({ date: 'You must define the period parameter as custom' }) unless @options[:period] == 'custom'
|
74
|
+
date_array = @options[:date].split(",")
|
75
|
+
errors.push({ date: 'You must define start and end dates divided by comma' }) unless date_array.length == 2
|
76
|
+
regex = /\d{4}\-\d{2}\-\d{2}/
|
77
|
+
errors.push({ date: 'Wrong format for the start date' }) unless date_array[0] =~ regex
|
78
|
+
errors.push({ date: 'Wrong format for the end date' }) unless date_array[1] =~ regex
|
79
|
+
end
|
80
|
+
errors
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlausibleApi
|
4
|
+
module Stats
|
5
|
+
class Breakdown < Base
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
super({ period: '30d', property: 'event:page' }.merge(options))
|
9
|
+
end
|
10
|
+
|
11
|
+
def request_url_base
|
12
|
+
"/api/v1/stats/breakdown?site_id=$SITE_ID"
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_response(body)
|
16
|
+
JSON.parse(body)['results']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module PlausibleApi
|
4
4
|
module Stats
|
5
5
|
module Realtime
|
6
|
-
class Visitors
|
7
|
-
def
|
6
|
+
class Visitors < PlausibleApi::Stats::Base
|
7
|
+
def request_url_base
|
8
|
+
"/api/v1/stats/realtime/visitors?site_id=$SITE_ID"
|
8
9
|
end
|
9
10
|
|
10
|
-
def
|
11
|
-
|
11
|
+
def parse_response(body)
|
12
|
+
body.to_i
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
@@ -2,25 +2,18 @@
|
|
2
2
|
|
3
3
|
module PlausibleApi
|
4
4
|
module Stats
|
5
|
-
class Timeseries
|
5
|
+
class Timeseries < Base
|
6
|
+
|
6
7
|
def initialize(options = {})
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
super({ period: '30d' }.merge(options))
|
9
|
+
end
|
10
|
+
|
11
|
+
def request_url_base
|
12
|
+
"/api/v1/stats/timeseries?site_id=$SITE_ID"
|
10
13
|
end
|
11
14
|
|
12
|
-
def
|
13
|
-
|
14
|
-
if @period
|
15
|
-
url += "&period=#{@period}"
|
16
|
-
end
|
17
|
-
if @filters
|
18
|
-
url += "&filters=#{CGI.escape(@filters)}"
|
19
|
-
end
|
20
|
-
if @date
|
21
|
-
url += "&date=#{@date}"
|
22
|
-
end
|
23
|
-
url
|
15
|
+
def parse_response(body)
|
16
|
+
JSON.parse(body)['results']
|
24
17
|
end
|
25
18
|
end
|
26
19
|
end
|
data/plausible_api.gemspec
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plausible_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
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-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: faraday
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.0'
|
11
|
+
date: 2021-02-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: A very humble wrapper for the new API by Plausible
|
28
14
|
email:
|
29
15
|
- gustavo@dailytics.com
|
@@ -43,6 +29,8 @@ files:
|
|
43
29
|
- lib/plausible_api.rb
|
44
30
|
- lib/plausible_api/client.rb
|
45
31
|
- lib/plausible_api/stats/aggregate.rb
|
32
|
+
- lib/plausible_api/stats/base.rb
|
33
|
+
- lib/plausible_api/stats/breakdown.rb
|
46
34
|
- lib/plausible_api/stats/realtime/visitors.rb
|
47
35
|
- lib/plausible_api/stats/timeseries.rb
|
48
36
|
- lib/plausible_api/version.rb
|