Skip to content

Commit 02f5199

Browse files
committed
introduce extended views per referrer
Add another view with bar chart and table showing requests per referrer. These views feature type and post filters. Data is retrieved via WP API.
1 parent cc4181f commit 02f5199

File tree

4 files changed

+290
-25
lines changed

4 files changed

+290
-25
lines changed

inc/class-statify-api.php

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Statify_Api extends Statify {
2727
const REST_ROUTE_STATS = 'stats';
2828
const REST_ROUTE_STATS_EXTENDED = 'stats/extended';
2929
const REST_ROUTE_STATS_POSTS = 'stats/posts';
30+
const REST_ROUTE_STATS_REFERRERS = 'stats/referrers';
3031
const REST_ROUTE_POSTS = 'posts';
3132

3233
/**
@@ -78,6 +79,16 @@ public static function init(): void {
7879
)
7980
);
8081

82+
register_rest_route(
83+
self::REST_NAMESPACE,
84+
self::REST_ROUTE_STATS_REFERRERS,
85+
array(
86+
'methods' => WP_REST_Server::READABLE,
87+
'callback' => array( __CLASS__, 'get_stats_referrers' ),
88+
'permission_callback' => array( __CLASS__, 'user_can_see_stats' ),
89+
)
90+
);
91+
8192
register_rest_route(
8293
self::REST_NAMESPACE,
8394
self::REST_ROUTE_POSTS,
@@ -280,7 +291,7 @@ public static function get_posts(): WP_REST_Response {
280291
function ( $url ) {
281292
return array(
282293
'url' => $url,
283-
'title' => self::post_title( $url ),
294+
'title' => Statify_Evaluation::post_title( $url ),
284295
);
285296
},
286297
Statify_Evaluation::get_post_urls()
@@ -310,9 +321,9 @@ public static function get_stats_posts( WP_REST_Request $request ): WP_REST_Resp
310321
return new WP_REST_Response( array( 'error' => 'invalid post type' ), 400 );
311322
}
312323

324+
// Date filter.
313325
$start = self::get_date( $request, 'start' );
314326
$end = self::get_date( $request, 'end' );
315-
316327
$data = false;
317328
if ( empty( $start ) && empty( $end ) ) {
318329
// Retrieve data from cache.
@@ -327,7 +338,7 @@ function ( $d ) {
327338
return array(
328339
'count' => intval( $d['count'] ),
329340
'url' => $url,
330-
'title' => self::post_title( $url ),
341+
'title' => Statify_Evaluation::post_title( $url ),
331342
'type' => $type,
332343
'typeName' => self::type_name( $type ),
333344
);
@@ -356,6 +367,40 @@ function ( $d ) use ( $type ) {
356367
return new WP_REST_Response( $data );
357368
}
358369

370+
/**
371+
* Get stats per referrers.
372+
*
373+
* @param WP_REST_Request $request The request.
374+
*
375+
* @return WP_REST_Response The response.
376+
*
377+
* @since 2.0.0
378+
*/
379+
public static function get_stats_referrers( WP_REST_Request $request ): WP_REST_Response {
380+
// Single post requested?
381+
$post = $request->get_param( 'post' );
382+
383+
// Date filter.
384+
$start = self::get_date( $request, 'start' );
385+
$end = self::get_date( $request, 'end' );
386+
$data = false;
387+
if ( empty( $post ) && empty( $start ) && empty( $end ) ) {
388+
// Retrieve data from cache.
389+
$data = self::from_cache( 'referrers' );
390+
}
391+
if ( ! $data ) {
392+
// Generate data for all types.
393+
$data = Statify_Evaluation::get_views_for_all_referrers( $post, $start, $end );
394+
395+
if ( empty( $post ) && empty( $start ) && empty( $end ) ) {
396+
// Store in cache.
397+
self::update_cache( 'referrers', '', $data );
398+
}
399+
}
400+
401+
return new WP_REST_Response( $data );
402+
}
403+
359404
/**
360405
* Retrieve data from cache.
361406
*
@@ -383,28 +428,6 @@ private static function update_cache( string $scope, string $index, array $data
383428
);
384429
}
385430

386-
/**
387-
* Get post title by URL.
388-
*
389-
* @param string $url Target URL.
390-
*
391-
* @return string Post title, fallback to URL of not available.
392-
*/
393-
private static function post_title( string $url ): string {
394-
if ( '' === $url ) {
395-
return __( 'all posts', 'statify' );
396-
}
397-
if ( '/' === $url ) {
398-
return __( 'Home Page', 'statify' );
399-
}
400-
$post_id = url_to_postid( $url );
401-
if ( 0 === $post_id ) {
402-
return esc_url( $url );
403-
}
404-
405-
return get_the_title( $post_id );
406-
}
407-
408431
/**
409432
* Get post type by URL.
410433
*

inc/class-statify-evaluation.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ public static function add_menu(): void {
6262
'statify_content',
6363
array( __CLASS__, 'show_content' )
6464
);
65+
66+
add_submenu_page(
67+
'statify_dashboard',
68+
__( 'Referrers', 'statify' ) . ' — ' . __( 'Statify', 'statify' ),
69+
__( 'Referrers', 'statify' ),
70+
'see_statify_evaluation',
71+
'statify_referrers',
72+
array( __CLASS__, 'show_referrers' )
73+
);
6574
}
6675

6776
/**
@@ -78,6 +87,13 @@ public static function show_content(): void {
7887
self::show_view( 'content' );
7988
}
8089

90+
/**
91+
* Show the referrers page.
92+
*/
93+
public static function show_referrers(): void {
94+
self::show_view( 'referrers' );
95+
}
96+
8197
/**
8298
* Load a specific page view.
8399
*
@@ -599,4 +615,26 @@ public static function get_post_types(): array {
599615

600616
return array_merge( array( 'post', 'page' ), get_post_types( $types_args ) );
601617
}
618+
619+
/**
620+
* Get post title by URL.
621+
*
622+
* @param string $url Target URL.
623+
*
624+
* @return string Post title, fallback to URL of not available.
625+
*/
626+
public static function post_title( string $url ): string {
627+
if ( '' === $url ) {
628+
return __( 'all posts', 'statify' );
629+
}
630+
if ( '/' === $url ) {
631+
return __( 'Home Page', 'statify' );
632+
}
633+
$post_id = url_to_postid( $url );
634+
if ( 0 === $post_id ) {
635+
return esc_url( $url );
636+
}
637+
638+
return get_the_title( $post_id );
639+
}
602640
}

js/dashboard.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
const chartElemMonthly = document.getElementById('statify_chart_monthly');
1717
const chartElemYearly = document.getElementById('statify_chart_yearly');
1818
const chartElemContent = document.getElementById('statify_chart_content');
19+
const chartElemReferrer = document.getElementById('statify_chart_referrer');
1920
const yearlyTable = document.getElementById('statify-table-yearly');
2021
const dailyTable = document.getElementById('statify-table-daily');
2122
const contentTable = document.getElementById('statify-table-posts');
23+
const referrersTable = document.getElementById('statify-table-referrer');
2224

2325
// Controls.
2426
const postInput = document.getElementById('statify-dashboard-post');
@@ -123,6 +125,28 @@
123125
});
124126
}
125127

128+
/**
129+
* Load statistics per referrer.
130+
*
131+
* @return {Promise<Array<{count: number, host: string, url: string}>>} Data promise from API.
132+
*/
133+
function loadPerReferrer() {
134+
const param = new URLSearchParams();
135+
const search = new URLSearchParams(window.location.search);
136+
['post', 'start', 'end'].forEach((p) => {
137+
const v = search.get(p);
138+
if (v) {
139+
param.set(p, v);
140+
}
141+
});
142+
143+
return wp.apiFetch({
144+
path:
145+
'/statify/v1/stats/referrers' +
146+
(param.size > 0 ? '?' + param : ''),
147+
});
148+
}
149+
126150
/**
127151
* Render daily statistics.
128152
*
@@ -613,6 +637,52 @@
613637
addExportButton(table);
614638
}
615639

640+
/**
641+
* Render referrers table.
642+
*
643+
* @param {HTMLTableElement} table Root element.
644+
* @param {Array<{count: number, host: string, url: string}>} data Data from API.
645+
*/
646+
function renderReferrersTable(table, data) {
647+
const tbody = table.querySelector('tbody');
648+
const sumRow = table.querySelectorAll('tfoot > tr > td');
649+
const rows = Array.from(tbody.querySelectorAll('tr'));
650+
651+
const total = data.map((d) => d.count).reduce((a, b) => a + b, 0);
652+
653+
data.forEach((d, idx) => {
654+
const row = document.createElement('TR');
655+
let col = document.createElement('TD');
656+
const link = document.createElement('A');
657+
link.href = d.url;
658+
link.innerText = d.host;
659+
col.append(link);
660+
row.appendChild(col);
661+
col = document.createElement('TD');
662+
col.classList.add('right');
663+
col.innerText = d.count.toString();
664+
row.appendChild(col);
665+
col = document.createElement('TD');
666+
col.classList.add('right');
667+
col.innerText = ((d.count / total) * 100).toFixed(2) + ' %';
668+
row.appendChild(col);
669+
670+
if (rows.length > idx) {
671+
tbody.replaceChild(row, rows[idx]);
672+
} else {
673+
tbody.appendChild(row);
674+
}
675+
});
676+
for (let i = data.length; i < rows.length; i++) {
677+
tbody.removeChild(rows[i]);
678+
}
679+
680+
sumRow[sumRow.length - 2].innerText = total;
681+
sumRow[sumRow.length - 1].innerText = '100.00 %';
682+
683+
addExportButton(table);
684+
}
685+
616686
/**
617687
* Convert daily to monthly data.
618688
*
@@ -694,6 +764,17 @@
694764
renderBarChart(chartElemContent, labels, values, true);
695765
}
696766
});
767+
} else if (referrersTable) {
768+
loadPerReferrer().then((data) => {
769+
renderReferrersTable(referrersTable, data);
770+
if (chartElemReferrer) {
771+
// Limit number of records.
772+
data = data.slice(0, 24);
773+
const labels = data.map((d) => d.host);
774+
const values = data.map((d) => d.count);
775+
renderBarChart(chartElemReferrer, labels, values, true);
776+
}
777+
});
697778
}
698779

699780
if (postInput && postList) {

0 commit comments

Comments
 (0)