1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Zernio API
*
* API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
*
* The version of the OpenAPI document: 1.0.4
* Contact: support@zernio.com
* Generated by: https://openapi-generator.tech
*/
use crate::models;
use serde::{Deserialize, Serialize};
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct AdMetrics {
#[serde(rename = "spend", skip_serializing_if = "Option::is_none")]
pub spend: Option<f64>,
#[serde(rename = "impressions", skip_serializing_if = "Option::is_none")]
pub impressions: Option<i32>,
#[serde(rename = "reach", skip_serializing_if = "Option::is_none")]
pub reach: Option<i32>,
#[serde(rename = "clicks", skip_serializing_if = "Option::is_none")]
pub clicks: Option<i32>,
/// Click-through rate (%)
#[serde(rename = "ctr", skip_serializing_if = "Option::is_none")]
pub ctr: Option<f64>,
/// Cost per click
#[serde(rename = "cpc", skip_serializing_if = "Option::is_none")]
pub cpc: Option<f64>,
/// Cost per 1000 impressions
#[serde(rename = "cpm", skip_serializing_if = "Option::is_none")]
pub cpm: Option<f64>,
#[serde(rename = "engagement", skip_serializing_if = "Option::is_none")]
pub engagement: Option<i32>,
/// Count of conversion events matching the campaign's promoted_object.custom_event_type (PURCHASE, LEAD, etc.) over the requested date range. 0 for non-conversion campaigns or when no events have fired. Meta-only at time of writing; other platforms return 0.
#[serde(rename = "conversions", skip_serializing_if = "Option::is_none")]
pub conversions: Option<i32>,
/// Derived spend / conversions in the same currency as spend. 0 when conversions is 0.
#[serde(rename = "costPerConversion", skip_serializing_if = "Option::is_none")]
pub cost_per_conversion: Option<f64>,
/// Raw per-action-type counts from Meta's Insights actions[] array, summed over the date range. Keys are Meta action_type strings (e.g. link_click, offsite_conversion.fb_pixel_purchase, onsite_conversion.lead_grouped). Use this to extract any conversion event (purchases, leads, add_to_cart, etc.) without relying on the derived conversions field. Empty object when no actions are reported.
#[serde(rename = "actions", skip_serializing_if = "Option::is_none")]
pub actions: Option<std::collections::HashMap<String, i32>>,
/// Monetary mirror of `actions`, from Meta's Insights `action_values[]` array. Same keying — values are the revenue attributed to each action_type, in ad-account native currency (same unit as `spend`; see the campaign node's `currency` field). Use this to compute revenue-per-event (e.g. avg purchase value). Meta-only; other platforms return {}.
#[serde(rename = "actionValues", skip_serializing_if = "Option::is_none")]
pub action_values: Option<std::collections::HashMap<String, f64>>,
/// Convenience sum of purchase-type action values — picked from `actionValues` via the same priority list as `conversions` so both fields describe the same events. In ad-account native currency. 0 when the campaign has no purchase event configured. Meta-only.
#[serde(rename = "purchaseValue", skip_serializing_if = "Option::is_none")]
pub purchase_value: Option<f64>,
/// Return on ad spend — derived as `purchaseValue / spend`. 0 when `spend` is 0. Equivalent to Meta's `purchase_roas` under default attribution. At ad-set and campaign levels this is recomputed from summed purchaseValue + spend (NOT averaged across children) so it's mathematically correct at every rollup level.
#[serde(rename = "roas", skip_serializing_if = "Option::is_none")]
pub roas: Option<f64>,
/// Meta video ads only (0 for non-video ads and other platforms), like all video* fields below. Number of times the video started playing (Meta `video_play_actions`), summed over the date range and across children at ad-set/campaign level.
#[serde(rename = "videoPlayActions", skip_serializing_if = "Option::is_none")]
pub video_play_actions: Option<i32>,
/// Views of at least 30 seconds (or to the end, for shorter videos). Meta `video_30_sec_watched_actions`.
#[serde(
rename = "video30SecWatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video30_sec_watched_actions: Option<i32>,
/// ThruPlays (watched to completion, or at least 15 seconds). Meta `video_thruplay_watched_actions`.
#[serde(
rename = "videoThruplayWatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_thruplay_watched_actions: Option<i32>,
/// Views reaching 25% of the video's length. With the other percentile fields, powers hook/hold/drop-off analysis (e.g. hook rate = videoP25WatchedActions / videoPlayActions). Meta `video_p25_watched_actions`.
#[serde(
rename = "videoP25WatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_p25_watched_actions: Option<i32>,
/// Views reaching 50% of the video's length. Meta `video_p50_watched_actions`.
#[serde(
rename = "videoP50WatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_p50_watched_actions: Option<i32>,
/// Views reaching 75% of the video's length. Meta `video_p75_watched_actions`.
#[serde(
rename = "videoP75WatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_p75_watched_actions: Option<i32>,
/// Views reaching 95% of the video's length. Meta `video_p95_watched_actions`.
#[serde(
rename = "videoP95WatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_p95_watched_actions: Option<i32>,
/// Views reaching 100% of the video's length. Meta `video_p100_watched_actions`.
#[serde(
rename = "videoP100WatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_p100_watched_actions: Option<i32>,
/// Average seconds watched per play (Meta `video_avg_time_watched_actions`). Aggregated over date ranges and across children as a play-weighted average (total watch time / total plays), never a plain average of averages.
#[serde(
rename = "videoAvgTimeWatchedActions",
skip_serializing_if = "Option::is_none"
)]
pub video_avg_time_watched_actions: Option<f64>,
/// Present on individual ads only, not on campaign aggregations
#[serde(rename = "lastSyncedAt", skip_serializing_if = "Option::is_none")]
pub last_synced_at: Option<String>,
}
impl AdMetrics {
pub fn new() -> AdMetrics {
AdMetrics {
spend: None,
impressions: None,
reach: None,
clicks: None,
ctr: None,
cpc: None,
cpm: None,
engagement: None,
conversions: None,
cost_per_conversion: None,
actions: None,
action_values: None,
purchase_value: None,
roas: None,
video_play_actions: None,
video30_sec_watched_actions: None,
video_thruplay_watched_actions: None,
video_p25_watched_actions: None,
video_p50_watched_actions: None,
video_p75_watched_actions: None,
video_p95_watched_actions: None,
video_p100_watched_actions: None,
video_avg_time_watched_actions: None,
last_synced_at: None,
}
}
}