Files
zeekay 1df3ddf6bd Regenerate against the document the deployment answers for
The projection these were generated from predated the compute migration, so
they described /v1/visor — which the API serves at zero paths now.

No /v1/visor path survives here.
2026-09-05 18:55:38 -07:00

125 lines
6.6 KiB
Swift

//
// CampaignResults.swift
//
// Generated by openapi-generator
// https://openapi-generator.tech
//
import Foundation
public struct CampaignResults: Sendable, Codable, ParameterConvertible, Hashable {
public var abTest: JSONValue?
/** Available is false when the analytics warehouse is not connected or the query failed: the funnel below is then zero because nothing could be read, not because nothing happened. Spend and Channels are still real — they come from the connectors, not the warehouse. */
public var available: Bool?
/** CAC is customer acquisition cost: spend DOLLARS per conversion, rounded to cents. 0 when nothing converted — that is \"not yet computable\", not \"free\". */
public var cac: Double?
/** CampaignID is the campaign these results are for, echoed from the request. */
public var campaignId: String?
/** Channels is the per-channel spend breakdown that SpendCents sums, one row per channel on the campaign including the ones that never launched. */
public var channels: [ChannelMetric]?
/** Clicks is the campaign's click events over the window. */
public var clicks: Int64?
/** Conversions is the terminal funnel events attributed to the campaign — orders completed, signups completed, explicit conversion events. */
public var conversions: Int64?
/** CTR is clicks per impression, a fraction rounded to 4 places (0.0123 = 1.23%), not a percentage. 0 when there were no impressions to divide by. */
public var ctr: Double?
/** CVR is conversions per click, a fraction rounded to 4 places. 0 when there were no clicks. */
public var cvr: Double?
/** End is the window's end, RFC3339 UTC — the read's own clock unless an explicit pair was given. The window is a LOOKBACK, not the campaign's own lifetime. */
public var end: String?
/** Impressions is how many times the campaign's creatives were shown, counted from its utm_campaign-tagged impression events. */
public var impressions: Int64?
/** Name is the campaign's display name at read time, so a result can be labelled without a second fetch. */
public var name: String?
/** Range is the window actually used: 24h, 7d, 30d, 90d, or \"custom\" when an explicit start/end pair was honored. An unparseable or absent range reads 30d, so this is the value to trust, not the one that was sent. */
public var range: String?
/** Revenue is the summed revenue attribute of the campaign's events, in whole CURRENCY UNITS (dollars) — the one money value here that is not in cents. */
public var revenue: Double?
/** ROAS is return on ad spend: revenue per spend DOLLAR, rounded to 2 places (2.5 = $2.50 back per $1). 0 when nothing was spent. */
public var roas: Double?
/** Source names the analytics table the funnel was read from, so an operator can see exactly what was counted. Set even when Available is false. */
public var source: String?
/** SpendCents is the campaign's total spend in CENTS: the sum of what each live channel's provider reports. A channel whose spend could not be read contributes 0 and says so on its own row. */
public var spendCents: Int64?
/** Start is the window's inclusive start, RFC3339 UTC. */
public var start: String?
/** Status is the campaign's lifecycle state at read time — draft, live, paused, completed or failed. A draft has never run, so its funnel is legitimately zero. */
public var status: String?
/** Visitors is how many distinct people the campaign reached, counted by event identity across ALL its events in the window — not a subset of Impressions, so it can exceed them for a campaign whose provider reports clicks but not views. */
public var visitors: Int64?
public init(abTest: JSONValue? = nil, available: Bool? = nil, cac: Double? = nil, campaignId: String? = nil, channels: [ChannelMetric]? = nil, clicks: Int64? = nil, conversions: Int64? = nil, ctr: Double? = nil, cvr: Double? = nil, end: String? = nil, impressions: Int64? = nil, name: String? = nil, range: String? = nil, revenue: Double? = nil, roas: Double? = nil, source: String? = nil, spendCents: Int64? = nil, start: String? = nil, status: String? = nil, visitors: Int64? = nil) {
self.abTest = abTest
self.available = available
self.cac = cac
self.campaignId = campaignId
self.channels = channels
self.clicks = clicks
self.conversions = conversions
self.ctr = ctr
self.cvr = cvr
self.end = end
self.impressions = impressions
self.name = name
self.range = range
self.revenue = revenue
self.roas = roas
self.source = source
self.spendCents = spendCents
self.start = start
self.status = status
self.visitors = visitors
}
public enum CodingKeys: String, CodingKey, CaseIterable {
case abTest
case available
case cac
case campaignId
case channels
case clicks
case conversions
case ctr
case cvr
case end
case impressions
case name
case range
case revenue
case roas
case source
case spendCents
case start
case status
case visitors
}
// Encodable protocol methods
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(abTest, forKey: .abTest)
try container.encodeIfPresent(available, forKey: .available)
try container.encodeIfPresent(cac, forKey: .cac)
try container.encodeIfPresent(campaignId, forKey: .campaignId)
try container.encodeIfPresent(channels, forKey: .channels)
try container.encodeIfPresent(clicks, forKey: .clicks)
try container.encodeIfPresent(conversions, forKey: .conversions)
try container.encodeIfPresent(ctr, forKey: .ctr)
try container.encodeIfPresent(cvr, forKey: .cvr)
try container.encodeIfPresent(end, forKey: .end)
try container.encodeIfPresent(impressions, forKey: .impressions)
try container.encodeIfPresent(name, forKey: .name)
try container.encodeIfPresent(range, forKey: .range)
try container.encodeIfPresent(revenue, forKey: .revenue)
try container.encodeIfPresent(roas, forKey: .roas)
try container.encodeIfPresent(source, forKey: .source)
try container.encodeIfPresent(spendCents, forKey: .spendCents)
try container.encodeIfPresent(start, forKey: .start)
try container.encodeIfPresent(status, forKey: .status)
try container.encodeIfPresent(visitors, forKey: .visitors)
}
}