late 0.0.894

API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
Documentation
/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api  Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal.  Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
 *
 * 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 PostAnalytics {
    #[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 = "likes", skip_serializing_if = "Option::is_none")]
    pub likes: Option<i32>,
    #[serde(rename = "comments", skip_serializing_if = "Option::is_none")]
    pub comments: Option<i32>,
    #[serde(rename = "shares", skip_serializing_if = "Option::is_none")]
    pub shares: Option<i32>,
    /// Number of saves/bookmarks (Instagram, Pinterest, X)
    #[serde(rename = "saves", skip_serializing_if = "Option::is_none")]
    pub saves: Option<i32>,
    #[serde(rename = "clicks", skip_serializing_if = "Option::is_none")]
    pub clicks: Option<i32>,
    #[serde(rename = "views", skip_serializing_if = "Option::is_none")]
    pub views: Option<i32>,
    /// Instagram feed posts and stories only: organic accounts that started following from this post. Null on Instagram Reels and non-Reels video, where Meta does not expose this metric for the media. 0 for other platforms.
    #[serde(
        rename = "follows",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub follows: Option<Option<i32>>,
    /// Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.
    #[serde(
        rename = "igReelsAvgWatchTime",
        skip_serializing_if = "Option::is_none"
    )]
    pub ig_reels_avg_watch_time: Option<i32>,
    /// Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
    #[serde(
        rename = "igReelsVideoViewTotalTime",
        skip_serializing_if = "Option::is_none"
    )]
    pub ig_reels_video_view_total_time: Option<i32>,
    /// Instagram Reels only: percentage (0-100) of initial views that skipped the reel within its first 3 seconds, as reported by Meta. Meta labels the metric estimated and in development, so it can move between syncs. 0 for non-Reels media and other platforms. When a post is published to several accounts, the aggregate is weighted by views.
    #[serde(rename = "reelsSkipRate", skip_serializing_if = "Option::is_none")]
    pub reels_skip_rate: Option<f64>,
    /// Instagram accounts connected with Facebook Login only: reposts of the media by other users, minus deleted reposts, on feed posts, reels and stories. Meta does not expose this metric for accounts connected with Instagram Login, so those always report 0. 0 for other platforms, including Threads, where reposts are counted in shares instead.
    #[serde(rename = "reposts", skip_serializing_if = "Option::is_none")]
    pub reposts: Option<i32>,
    /// Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
    #[serde(
        rename = "videoDurationSeconds",
        default,
        with = "::serde_with::rust::double_option",
        skip_serializing_if = "Option::is_none"
    )]
    pub video_duration_seconds: Option<Option<i32>>,
    /// Percentage, rounded to 2 decimals: (likes + comments + shares + saves) / (impressions or reach or views) * 100. Clicks and follows are never counted. The denominator is the FIRST of impressions, reach, views that is non-zero, so it is not the same basis on every post: a post with impressions divides by impressions, one without falls back to reach, then to views. If you need a single consistent basis (e.g. interactions / reach), compute it from the raw fields above. The engagementRate on the LinkedIn account endpoints is a different formula.
    #[serde(rename = "engagementRate", skip_serializing_if = "Option::is_none")]
    pub engagement_rate: Option<f64>,
    #[serde(rename = "lastUpdated", skip_serializing_if = "Option::is_none")]
    pub last_updated: Option<String>,
}

impl PostAnalytics {
    pub fn new() -> PostAnalytics {
        PostAnalytics {
            impressions: None,
            reach: None,
            likes: None,
            comments: None,
            shares: None,
            saves: None,
            clicks: None,
            views: None,
            follows: None,
            ig_reels_avg_watch_time: None,
            ig_reels_video_view_total_time: None,
            reels_skip_rate: None,
            reposts: None,
            video_duration_seconds: None,
            engagement_rate: None,
            last_updated: None,
        }
    }
}