<?php
|
namespace JVBase\integrations\services;
|
use JVBase\integrations\Admin;
|
use JVBase\Instance;
|
use JVBase\integrations\Integrations;
|
use JVBase\managers\Roles;
|
use JVBase\registrar\Registrar;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
class Umami extends Integrations
|
{
|
use Admin, Instance;
|
|
protected function __construct()
|
{
|
$this->service_name = 'umami';
|
$this->title = 'umami';
|
$this->icon = 'chart-line';
|
|
$this->defineFields();
|
$this->defineInstructions();
|
|
parent::__construct();
|
$this->defineTables();
|
}
|
|
protected function defineFields(): void
|
{
|
$id = $this->addField('website_id', 'Website ID', 'text', 'manage_options');
|
$id->setHint('Found in your Umami dashboard under Settings->Websites');
|
$id->setRequired();
|
|
$api_url = $this->addField('api_url', 'API URL', 'text', 'manage_options');
|
$api_url->setHint('Your Umami server URL. Leave blank if using umami.is cloud service.');
|
|
$api_token = $this->addField('api_token', 'API Token (Optional)', 'text', 'manage_options');
|
$api_token->setSubType('password');
|
$api_token->setHint('Required only if you want to retrieve analytics data for dashboards.');
|
}
|
protected function defineInstructions():void
|
{
|
$this->instructions = [
|
'Login to your <a href="https://cloud.umami.is/settings/websites" target="_blank">umami.is</a> account, select your website, and copy the website ID'
|
];
|
}
|
|
protected function defineTables():void
|
{
|
//TODO: Once we have an actual umami setup, we can store the fetched data here for reference
|
//Ideally, we have the type (term, user, post), WP ID, created_date, and count
|
}
|
|
protected function initialize(): void
|
{
|
// Add tracking script to frontend
|
add_action('wp_head', [$this, 'renderTrackingScript'], 5);
|
|
// Schedule data collection if API is configured
|
if ($this->getApiToken()) {
|
add_action('jvb_daily_umami_collection', [$this, 'collectDailyData']);
|
|
if (!wp_next_scheduled('jvb_daily_umami_collection')) {
|
wp_schedule_event(time(), 'daily', 'jvb_daily_umami_collection');
|
}
|
}
|
}
|
|
public function renderTrackingScript():void
|
{
|
if (JVB_TESTING || !$this->isSetUp() || is_admin()) {
|
return;
|
}
|
|
$script_url = $this->getTrackingScriptUrl();
|
if (!$this->getWebsiteID() || empty($script_url)) {
|
return;
|
}
|
|
echo sprintf(
|
'<link rel="preconnect" href="https://%s"/>' . "\n",
|
esc_attr(parse_url($script_url, PHP_URL_HOST))
|
);
|
|
$attributes = [
|
'defer',
|
sprintf(
|
'src="%s"',
|
esc_url($script_url)
|
),
|
sprintf(
|
'data-website-id="%s"',
|
esc_attr($this->getWebsiteID())
|
)
|
];
|
|
$tags = $this->getCurrentTag();
|
if (!empty($tags)) {
|
$attributes[] = $tags;
|
}
|
|
echo sprintf(
|
'<script %s></script>',
|
implode(' ', $attributes)
|
);
|
|
$this->outputCustomEvent();
|
}
|
protected function getCurrentTag():string
|
{
|
$contentTax = array_map('jvbCheckBase', Registrar::withFeature('is_content', 'term'));
|
if (!empty($contentTax) && is_tax($contentTax)) {
|
$tax = get_queried_object();
|
$reg = Registrar::getInstance($tax->taxonomy);
|
return 'data-tag="'.$reg->getUmamiEvent().'"';
|
}
|
|
$profiles = array_map('jvbCheckBase', Registrar::withFeature('profile_link'));
|
if (!empty($profiles) && is_singular($profiles)) {
|
$usr = get_queried_object();
|
$reg = Registrar::getInstance($usr->post_type);
|
return 'data-tag="'.$reg->getUmamiEvent().'"';
|
}
|
|
return '';
|
}
|
|
protected function outputCustomEvent():void
|
{
|
$args = [];
|
$event = false;
|
$contentTax = array_map('jvbCheckBase', Registrar::withFeature('is_content', 'term'));
|
if (!empty($contentTax) && is_tax($contentTax)) {
|
$tax = get_queried_object();
|
$reg = Registrar::getInstance($tax->taxonomy);
|
|
$event = $reg->getUmamiEvent();
|
$args = [
|
'id' => $tax->term_id,
|
];
|
if ($reg->isOwnable()) {
|
$owners = jvbGetTermOwners($tax->term_id);
|
if (!empty($owners)) {
|
$args['owners'] = $owners;
|
}
|
}
|
}
|
|
$profiles = array_map('jvbCheckBase', Registrar::withFeature('profile_link'));
|
if (!empty($profiles) && is_singular($profiles)) {
|
$usr = get_queried_object();
|
$reg = Registrar::getInstance($usr->post_type);
|
$event = $reg->getUmamiEvent();
|
|
global $post;
|
$args['id'] = get_the_ID();
|
$args['owner_id'] = $post->post_author;
|
}
|
|
if ($event && !empty($args)) {
|
echo sprintf(
|
'<script defer>umami.track(event_name: %s, data: %s);</script>',
|
$event,
|
json_encode($args)
|
);
|
}
|
}
|
|
/*********************************************************
|
* UTILITY
|
*********************************************************/
|
public function getWebsiteID(): string|false
|
{
|
return $this->loadCredentials()['website_id']??false;
|
}
|
protected function getApiUrl():string|false
|
{
|
$api = $this->loadCredentials()['api_url'];
|
return empty($api) ? false : $api;
|
}
|
protected function getApiToken():string|false
|
{
|
$api = $this->loadCredentials()['api_token'];
|
return empty($api) ? false : $api;
|
}
|
protected function getTrackingScriptUrl():string
|
{
|
if ($this->getApiUrl()) {
|
return rtrim($this->getApiUrl(), '/').'/script.js';
|
}
|
// Default to Umami cloud
|
return 'https://cloud.umami.is/script.js';
|
}
|
|
public function buildEvent(string $event, array $args = []):string
|
{
|
$base = 'data-umami-event';
|
$out = [
|
$base => esc_attr($event),
|
];
|
|
foreach ($args as $k => $v) {
|
$out[$base.$k] = esc_attr(jvbNoBase($v));
|
}
|
|
return $this->attributesToString($out);
|
}
|
|
protected function attributesToString(array $attributes):string
|
{
|
$strings = [];
|
foreach ($attributes as $key => $value) {
|
$strings[] = sprintf(
|
'%s="%s"',
|
$key,
|
$value
|
);
|
}
|
|
return implode(' ', $strings);
|
}
|
}
|