Skip to main content

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

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