oranda 0.6.5

🎁 generate beautiful landing pages for your projects
Documentation
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::config::AnalyticsConfig;

#[derive(Serialize, Debug, Default)]
pub struct Analytics {
    pub snippet: Option<String>,
    pub google_script: Option<String>,
}

impl Analytics {
    pub fn new(config: &Option<AnalyticsConfig>) -> Self {
        if let Some(analytics) = config {
            match analytics {
                AnalyticsConfig::Google(provider) => {
                    let google_script = Some(provider.get_script());
                    Self {
                        snippet: Some(provider.snippet()),
                        google_script,
                    }
                }
                AnalyticsConfig::Plausible(provider) => Self::build(provider),
                AnalyticsConfig::Fathom(provider) => Self::build(provider),
                AnalyticsConfig::Umami(provider) => Self::build(provider),
            }
        } else {
            Self {
                snippet: None,
                google_script: None,
            }
        }
    }

    fn build<T: Snippet>(provider: &T) -> Self {
        Self {
            snippet: Some(provider.snippet()),
            google_script: None,
        }
    }
}

#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
pub struct Google {
    pub tracking_id: String,
}

#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
pub struct Fathom {
    pub site: String,
}

#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
pub struct Plausible {
    pub domain: String,
    pub script_url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)]
pub struct Umami {
    pub website: String,
    pub script_url: String,
}

const GOOGLE_SCRIPT_URL: &str = "https://www.googletagmanager.com/gtag/js";
const PLAUSIBLE_SCRIPT_URL: &str = "https://plausible.io/js/script.js";
const FATHOM_SCRIPT_URL: &str = "https://cdn.usefathom.com/script.js";

impl Google {
    pub fn get_script(&self) -> String {
        format!("window.dataLayer = window.dataLayer || []; function gtag(){{dataLayer.push(arguments);}} gtag('js', new Date());gtag('config', '{}');", self.tracking_id)
    }
}

trait Snippet {
    fn snippet(&self) -> String;
}

impl Snippet for Google {
    fn snippet(&self) -> String {
        let script_url = format!("{}?id={}", GOOGLE_SCRIPT_URL, self.tracking_id);
        format!(r#"<script async="true" src="{script_url}"></script>"#)
    }
}

impl Snippet for Fathom {
    fn snippet(&self) -> String {
        format!(
            r#"<script defer="true" src="{FATHOM_SCRIPT_URL}" data-site="{}"></script>"#,
            self.site
        )
    }
}

impl Snippet for Umami {
    fn snippet(&self) -> String {
        format!(
            r#"<script async="true" defer="true" src="{}" data-website-id="{}"></script>"#,
            self.script_url, self.website
        )
    }
}

impl Snippet for Plausible {
    fn snippet(&self) -> String {
        let url = PLAUSIBLE_SCRIPT_URL.to_string();
        let script_url = self.script_url.as_ref().unwrap_or(&url);
        format!(
            r#"<script defer="true" data-domain="{}" src="{script_url}"></script>"#,
            self.domain
        )
    }
}