Skip to main content

systemprompt_cli/commands/core/content/analytics/
campaign.rs

1//! `core content analytics campaign` command.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use crate::cli_settings::CliConfig;
7use crate::commands::core::content::types::CampaignAnalyticsOutput;
8use crate::context::CommandContext;
9use crate::shared::CommandOutput;
10use anyhow::{Result, anyhow};
11use clap::Args;
12use systemprompt_content::LinkAnalyticsService;
13use systemprompt_database::DbPool;
14use systemprompt_identifiers::CampaignId;
15
16#[derive(Debug, Args)]
17pub struct CampaignArgs {
18    #[arg(help = "Campaign ID")]
19    pub campaign_id: String,
20}
21
22pub async fn execute(args: CampaignArgs, ctx: &CommandContext) -> Result<CommandOutput> {
23    execute_with_pool(args, &ctx.db_pool().await?, &ctx.cli).await
24}
25
26pub async fn execute_with_pool(
27    args: CampaignArgs,
28    pool: &DbPool,
29    _config: &CliConfig,
30) -> Result<CommandOutput> {
31    let service = LinkAnalyticsService::new(pool)?;
32
33    let campaign_id = CampaignId::new(args.campaign_id.clone());
34    let performance = service
35        .get_campaign_performance(&campaign_id)
36        .await?
37        .ok_or_else(|| anyhow!("Campaign not found: {}", args.campaign_id))?;
38
39    let output = CampaignAnalyticsOutput {
40        campaign_id: performance.campaign_id,
41        total_clicks: performance.total_clicks,
42        link_count: performance.link_count,
43        unique_visitors: performance.unique_visitors.unwrap_or(0),
44        conversion_count: performance.conversion_count.unwrap_or(0),
45    };
46
47    Ok(CommandOutput::card_value("Campaign Analytics", &output))
48}