@prefix : <https://ontology.inferal.com/modules/advertising-measurement/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix mod: <https://w3id.org/mod#> .
@prefix ord: <https://ontology.inferal.com/modules/ordering/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix pubacc: <https://ontology.inferal.com/modules/publication-access/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rng: <https://ontology.inferal.com/modules/range/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix vann: <http://purl.org/vocab/vann/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

:
    a owl:Ontology, pubacc:PublicationManagedOntology ;
    dcterms:accessRights pubacc:PublicAccess ;
    owl:imports
        ord: ,
        rng: ,
        <http://www.w3.org/2004/02/skos/core> ,
        <http://www.w3.org/ns/prov> ,
        <http://www.w3.org/2006/time#> ;
    dcterms:title "Advertising Measurement Ontology" ;
    dcterms:description "Terms for stating an advertising metric observation so that observations from different providers are comparable, or provably not: reified observations, metric kinds, reporting windows, typed values, attribution bases, and time-bounded hierarchy membership." ;
    dcterms:license <https://creativecommons.org/licenses/by/4.0/> ;
    dcterms:source
        ord: ,
        rng: ,
        <http://www.w3.org/2004/02/skos/core> ,
        <http://www.w3.org/ns/prov> ,
        <http://www.w3.org/2006/time#> ;
    dcterms:references
        <https://www.w3.org/TR/vocab-data-cube/> ,
        <https://iabtechlab.com/standards/adcom-advertising-common-object-model/> ,
        <http://qudt.org/schema/qudt/> ;
    vann:preferredNamespacePrefix "adm" ;
    vann:preferredNamespaceUri "https://ontology.inferal.com/modules/advertising-measurement/" ;
    mod:status "draft" ;
    rdfs:comment "This module models the act of measuring an advertising entity, not the entities themselves. An observation is reified so it can carry the qualifiers that determine comparability: what was measured, over which window, at which grain, under which attribution basis, and sliced by which dimensions. Measurement is treated as a space rather than as numbers hanging off a container hierarchy, which is why partitioning axes such as placement, device, and country are breakdown dimensions rather than tiers: nobody owns a placement, so it can never be a subject. Provider report rows lower into observations rather than becoming classes, so a new provider composes from existing terms instead of adding provider-shaped ones. Hierarchy membership is reified for the same reason: containment changes over time, and an observation must be read against the hierarchy that held during its window. Entity tiers, targeting, creative payloads, and budgets are out of scope and are covered elsewhere." ;
    owl:versionInfo "0.1.0" .


# --- Observation -------------------------------------------------------------

:MetricObservation
    a rdfs:Class ;
    rdfs:subClassOf prov:Entity ;
    rdfs:label "metric observation" ;
    rdfs:comment "A single measured quantity about one advertising resource, qualified by the reporting window it covers, the grain it was reported at, the attribution basis under which it was computed, and any dimensions it is partitioned by. One provider report row yields as many observations as it carries measures." ;
    dcterms:description "Use one observation per measured quantity rather than a row-shaped record with many measure properties. Two observations are directly comparable only when their metric kind, grain, reporting window, attribution basis, and set of breakdowns all agree. The breakdown set matters as much as the rest: an unsliced total and the placement slices that partition it describe the same measure at different resolutions, so adding them together counts every impression twice. The reified form is what lets a rule refuse both mistakes." ;
    rdfs:seeAlso <https://www.w3.org/TR/vocab-data-cube/#dsd-observation> .


:AttributedMetricKind
    a rdfs:Class ;
    rdfs:subClassOf :MetricKind ;
    rdfs:label "attributed metric kind" ;
    rdfs:comment "A metric kind whose figure is produced by crediting outcomes to advertising under an attribution rule, rather than counted directly from delivery." ;
    dcterms:description "The distinction decides whether an attribution basis is meaningful. Impressions, clicks, and spend are counted as they happen and mean the same thing whatever crediting rule is in force. A conversion count does not exist until a rule decides which outcomes to credit, so the same population yields different figures under different rules, and a figure without its rule cannot be compared with anything. Provider profiles declare their own outcome kinds as members when the provider credits them." .


:ObservationGrain
    a rdfs:Class ;
    rdfs:label "observation grain" ;
    rdfs:comment "The tier of the advertising hierarchy that an observation's subject occupies: advertiser account, campaign, ad group, or individual ad." ;
    dcterms:description "Grain is stated explicitly because provider report rows do not carry it reliably. A metrics row may arrive with every dimension identifier optional, or with none at all, so grain cannot be recovered by inspecting which identifiers are populated. Summing observations across grains double-counts." .

:MetricKind
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "metric kind" ;
    rdfs:comment "The phenomenon an observation measures, independent of any provider's name or wire encoding for it." ;
    dcterms:description "Metric kinds are concepts rather than predicates so that a provider mapping points at a shared concept without the concept's identity depending on a predicate URI. This is the distinction that lets impressions reported as a string by one provider and an integer by another share a kind while keeping their literal encodings apart." .


# --- Reporting window --------------------------------------------------------

:ReportingWindow
    a rdfs:Class ;
    rdfs:subClassOf rng:Range ;
    rdfs:label "reporting window" ;
    rdfs:comment "The interval of time an observation's value covers, expressed as a range over temporal instants." ;
    dcterms:description "Specialising rng:Range rather than carrying a pair of date literals means window containment, overlap, and adjacency are answered by the shared range and ordering vocabulary instead of by per-provider date arithmetic. Providers ship at least four incompatible window shapes on the wire; all of them lower into this one." ;
    skos:hiddenLabel "date range", "reporting period", "date_start", "date_stop", "segments.date" .


# --- Values ------------------------------------------------------------------

:MetricValue
    a rdfs:Class ;
    rdfs:label "metric value" ;
    rdfs:comment "A measured magnitude carried by an observation, canonicalised to a decimal and typed by what kind of quantity it is." ;
    dcterms:description "Use a subclass rather than a bare literal. The subclass carries the arithmetic that is legal on the value: counts add, monetary amounts add only within a currency, and ratios do not add at all. A graph that stores every measure as a plain number cannot express that distinction, which is how derived ratios end up summed." .

:CountValue
    a rdfs:Class ;
    rdfs:subClassOf :MetricValue ;
    rdfs:label "count value" ;
    rdfs:comment "A non-negative count of discrete occurrences, such as impressions, clicks, or conversions. Counts are additive across observations that agree on kind, grain, and attribution basis." ;
    dcterms:description "Counts may be fractional despite counting discrete things: a provider that apportions a conversion across touchpoints reports a fraction. The canonical value is a decimal for that reason, not an integer." .

:MonetaryValue
    a rdfs:Class ;
    rdfs:subClassOf :MetricValue ;
    rdfs:label "monetary value" ;
    rdfs:comment "A quantity of money, such as spend or conversion value. Additive only among observations sharing a currency." ;
    dcterms:description "The currency lives on the associated monetary amount rather than on the observation, so a value cannot be recorded without one. Provider wire encodings vary between minor units, micros, and decimal strings; all lower to a decimal in major units here." .

:RatioValue
    a rdfs:Class ;
    rdfs:subClassOf :MetricValue ;
    rdfs:label "ratio value" ;
    rdfs:comment "A derived quotient such as click-through rate, cost per click, or return on ad spend. Not additive under any circumstances." ;
    dcterms:description "Ratios are recorded when a provider supplies them, but a consumer that needs a ratio over an aggregate must recompute it from the underlying additive observations. Averaging provider-supplied ratios across observations is arithmetically wrong whenever the denominators differ." .


:CostRateValue
    a rdfs:Class ;
    rdfs:subClassOf :MetricValue ;
    rdfs:label "cost rate value" ;
    rdfs:comment "An amount of money per unit of something counted, such as cost per click or cost per thousand impressions. Not additive, and not comparable across currencies." ;
    dcterms:description "Separated from a plain ratio because a cost rate is denominated. Two rates of four are the same number and different quantities when one is in dollars and the other in euro, so the currency-bearing amount is required here exactly as it is for spend. Separated from a monetary value because it is a rate: summing two of them is meaningless whatever the currency." .


:MonetaryAmount
    a rdfs:Class ;
    rdfs:label "monetary amount" ;
    rdfs:comment "An amount of money as a decimal quantity in major units paired with the ISO 4217 code of its currency." ;
    dcterms:description "Amount and currency are one resource because neither is meaningful alone. Recording them as two independent properties on a parent invites rows where the amount is present and the currency is absent, which is the state most provider analytics responses arrive in." ;
    rdfs:seeAlso <http://purl.org/goodrelations/v1#UnitPriceSpecification> ,
                 <https://spec.edmcouncil.org/fibo/ontology/FND/Accounting/CurrencyAmount/> .


# --- Attribution -------------------------------------------------------------

:AttributionBasis
    a rdfs:Class ;
    rdfs:label "attribution basis" ;
    rdfs:comment "The attribution model and lookback window under which a measured quantity was computed. Two observations computed under different bases are not comparable even when their kind and grain agree." ;
    dcterms:description "Attribution configuration is a property of how a number was produced, not of the entity measured, so it belongs on the observation. Providers variously store it as a result field, repeat it as free-text columns, or omit it entirely; leaving it implicit is what allows a cross-provider total to silently add numbers computed under incompatible rules." .

:CreditedInteraction
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "credited interaction" ;
    rdfs:comment "The kind of prior interaction an attribution basis will credit for an outcome, such as a click on the ad or merely an impression of it." ;
    dcterms:description "Providers express attribution as this crossed with a duration, so a basis stating only a model and a lookback cannot distinguish a click-attributed figure from a view-attributed one. The two differ by large factors on the same campaign, and summing across them overstates results." .

:AttributionModel
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "attribution model" ;
    rdfs:comment "The rule assigning credit for an outcome to prior advertising interactions, such as last click, first click, linear, or a provider's proprietary model." ;
    dcterms:description "Proprietary models are recorded as distinct concepts rather than mapped onto a standard one. Two providers' data-driven models are not the same rule and must not be conflated by a shared label." .

:Channel
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "channel" ;
    rdfs:comment "The advertising platform an advertiser buys through, distinct from the publisher property delivery occurred on." ;
    dcterms:description "Channel is a first-class dimension because measurement crosses platforms even when entities do not. It is stated on the observation rather than inferred from the subject's namespace, so that a measurement platform reporting on another vendor's inventory can name the delivering channel correctly." .


# --- Breakdowns --------------------------------------------------------------

:Breakdown
    a rdfs:Class ;
    rdfs:label "breakdown" ;
    rdfs:comment "A binding of one partitioning dimension to one of its values, qualifying an observation as covering only that slice of the measured population." ;
    dcterms:description "Reified because a breakdown is a pair, and providers flatten it: one ships a single string conflating the dimension name with its value, another repeats a column per dimension. Splitting the pair into a dimension and a value is what lets a consumer ask which dimensions an observation is sliced by without parsing labels. An observation with no breakdowns covers the whole population for its subject and window." ;
    rdfs:seeAlso <https://www.w3.org/TR/vocab-data-cube/#dsd-dimension> .

:BreakdownDimension
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "breakdown dimension" ;
    rdfs:comment "An axis along which a measured population can be partitioned, such as placement, device, or country." ;
    dcterms:description "Dimensions are distinct from the hierarchy tiers in ObservationGrain. A grain says what kind of thing the subject is; a dimension says how the measure over that subject was partitioned. Placement is a dimension rather than a tier precisely because nobody owns a placement: it is where delivery happened, not a resource in the account structure." .

:PublisherPlatform
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "publisher platform" ;
    rdfs:comment "The property an ad was delivered on, such as Facebook, Instagram, Messenger, or a partner audience network." ;
    dcterms:description "Distinct from the channel an advertiser buys through. One purchase on a single ads platform delivers across several publisher properties, so a figure attributed to the channel says nothing about which property produced it. Providers report the two separately, and conflating them loses the distinction." .

:PlacementSurface
    a rdfs:Class ;
    rdfs:subClassOf skos:Concept ;
    rdfs:label "placement surface" ;
    rdfs:comment "The surface within a publisher property that an ad occupied, such as an in-feed slot, a stories card, a reel, or a right-hand column. Named a surface rather than a placement because it is a kind of position, not the commitment that put an ad there." ;
    skos:altLabel "placement" ;
    dcterms:description "A surface, not a property. Providers report the two as separate dimensions and also offer a joined form whose values pre-combine them. The joined form lowers to two breakdowns here rather than one, because a value carrying two dimensions cannot be filtered on either alone. Positions are open-ended and provider profiles extend the scheme rather than minting parallel classes. A placement is never an observation subject." .


# --- Hierarchy membership ----------------------------------------------------

:HierarchyMembership
    a rdfs:Class ;
    rdfs:label "hierarchy membership" ;
    rdfs:comment "A first-class, time-bounded occurrence of one advertising resource being contained by another: an ad in an ad group, an ad group in a campaign, a campaign in an advertiser account." ;
    dcterms:description "Containment is reified because it changes. An ad moves between ad groups and a campaign is restructured, so a parent link asserted as a direct property silently rewrites the hierarchy that historical observations were measured under. The validity range states when the containment held, which is what lets an observation be read against the hierarchy in force during its own reporting window. Deliberately not a specialisation of set membership: a tier keeps its identity while its contents change, so it is a collection whose extension varies rather than a set whose extension defines it. Treating a campaign as a classical set would make two campaigns holding the same ad groups the same campaign." ;
    rdfs:seeAlso <https://ontology.inferal.com/modules/hypergraphs/> .


# --- Object properties -------------------------------------------------------

:observationSubject
    a rdf:Property ;
    rdfs:label "observation subject" ;
    rdfs:comment "The advertising resource the observation measures." ;
    rdfs:domain :MetricObservation ;
    rdfs:range rdfs:Resource .

:observationGrain
    a rdf:Property ;
    rdfs:label "has observation grain" ;
    rdfs:comment "The hierarchy tier the observation's subject occupies." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :ObservationGrain .

:metricKind
    a rdf:Property ;
    rdfs:label "has metric kind" ;
    rdfs:comment "The phenomenon the observation measures." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :MetricKind .

:reportingWindow
    a rdf:Property ;
    rdfs:label "has reporting window" ;
    rdfs:comment "The interval of time the observation's value covers." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :ReportingWindow .

:observedValue
    a rdf:Property ;
    rdfs:label "observed value" ;
    rdfs:comment "The measured magnitude the observation carries." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :MetricValue .

:attributionBasis
    a rdf:Property ;
    rdfs:label "has attribution basis" ;
    rdfs:comment "The model and lookback window under which the observation's value was computed." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :AttributionBasis .

:observedChannel
    a rdf:Property ;
    rdfs:label "observed channel" ;
    rdfs:comment "The advertising platform the observation's subject was delivered through." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :Channel .

:observationBreakdown
    a rdf:Property ;
    rdfs:label "observation breakdown" ;
    rdfs:comment "A dimension-value pair the observation is sliced by. An observation may carry several, one per dimension. Carrying none means the observation covers the whole population for its subject and window." ;
    rdfs:domain :MetricObservation ;
    rdfs:range :Breakdown .

:breakdownDimension
    a rdf:Property ;
    rdfs:label "has breakdown dimension" ;
    rdfs:comment "The axis a breakdown partitions along." ;
    rdfs:domain :Breakdown ;
    rdfs:range :BreakdownDimension .

:breakdownValue
    a rdf:Property ;
    rdfs:label "breakdown value" ;
    rdfs:comment "The value of the dimension this breakdown selects, such as a particular placement or country." ;
    rdfs:domain :Breakdown ;
    rdfs:range rdfs:Resource .

:windowStart
    a rdf:Property ;
    rdfs:subPropertyOf rng:lowerBound ;
    rdfs:label "window start" ;
    rdfs:comment "The instant a reporting window opens. Omitted when the window is unbounded below." ;
    rdfs:domain :ReportingWindow ;
    rdfs:range time:Instant .

:windowEnd
    a rdf:Property ;
    rdfs:subPropertyOf rng:upperBound ;
    rdfs:label "window end" ;
    rdfs:comment "The instant a reporting window closes. Omitted when the window is unbounded above, as for a lifetime total." ;
    rdfs:domain :ReportingWindow ;
    rdfs:range time:Instant .

:valueAmount
    a rdf:Property ;
    rdfs:label "value amount" ;
    rdfs:comment "The monetary amount a monetary value carries." ;
    rdfs:domain :MonetaryValue ;
    rdfs:range :MonetaryAmount .

:usedAttributionModel
    a rdf:Property ;
    rdfs:label "used attribution model" ;
    rdfs:comment "The credit-assignment rule the attribution basis applies." ;
    rdfs:domain :AttributionBasis ;
    rdfs:range :AttributionModel .

:creditedInteraction
    a rdf:Property ;
    rdfs:label "has credited interaction" ;
    rdfs:comment "The kind of interaction this basis credits. A basis crediting views and one crediting clicks are not comparable even at the same lookback duration." ;
    rdfs:domain :AttributionBasis ;
    rdfs:range :CreditedInteraction .

:lookbackWindow
    a rdf:Property ;
    rdfs:label "lookback window" ;
    rdfs:comment "The interval before an outcome within which a prior interaction can receive credit under this basis." ;
    rdfs:domain :AttributionBasis ;
    rdfs:range rng:Range .

:containedIn
    a rdf:Property ;
    rdfs:label "contained in" ;
    rdfs:comment "The containing advertising resource of a hierarchy membership: the ad group for an ad, the campaign for an ad group, the account for a campaign." ;
    rdfs:domain :HierarchyMembership ;
    rdfs:range rdfs:Resource .

:containedResource
    a rdf:Property ;
    rdfs:label "contained resource" ;
    rdfs:comment "The contained advertising resource of a hierarchy membership." ;
    rdfs:domain :HierarchyMembership ;
    rdfs:range rdfs:Resource .

:validityWindow
    a rdf:Property ;
    rdfs:label "validity window" ;
    rdfs:comment "The interval during which a hierarchy membership held. An open upper bound means the containment is current." ;
    rdfs:domain :HierarchyMembership ;
    rdfs:range rng:Range .


# --- Datatype properties -----------------------------------------------------

:canonicalMagnitude
    a rdf:Property ;
    rdfs:label "canonical magnitude" ;
    rdfs:comment "The value's magnitude as a decimal, in major currency units for monetary values and in whole or fractional occurrences for counts. Provider wire encodings such as minor units and micros are converted on the way in." ;
    rdfs:domain :MetricValue ;
    rdfs:range xsd:decimal .

:amountValue
    a rdf:Property ;
    rdfs:label "amount value" ;
    rdfs:comment "The numeric quantity of a monetary amount, in major units of its currency." ;
    rdfs:domain :MonetaryAmount ;
    rdfs:range xsd:decimal .

:currencyCode
    a rdf:Property ;
    rdfs:label "currency code" ;
    rdfs:comment "The ISO 4217 alphabetic code of a monetary amount's currency." ;
    rdfs:domain :MonetaryAmount ;
    rdfs:range xsd:string .


# --- Cross-provider property spine -------------------------------------------

:metricValue
    a rdf:Property ;
    rdfs:label "metric value" ;
    rdfs:comment "The common ancestor of every provider field that reports a measured advertising quantity. A provider field declares itself beneath this property, or beneath one of its arithmetic subproperties, with rdfs:subPropertyOf." ;
    dcterms:description "A join anchor, not an arithmetic licence. It carries no domain and no range so that provider fields of any subject class and any literal datatype can sit beneath it; one query over this property reaches spend on one provider and cost on another. Whether two reached values may be added or compared is stated by the subproperty they arrive through and by the observation model, not by this property." .

:countValue
    a rdf:Property ;
    rdfs:subPropertyOf :metricValue ;
    rdfs:label "count value" ;
    rdfs:comment "A provider field counting discrete occurrences, such as impressions, clicks, or conversions. Additive across observations that agree on kind, grain, and attribution basis." ;
    dcterms:description "The property spine's counterpart of the CountValue class. Counts may be fractional when a provider apportions an outcome across touchpoints." .

:monetaryValue
    a rdf:Property ;
    rdfs:subPropertyOf :metricValue ;
    rdfs:label "monetary value" ;
    rdfs:comment "A provider field carrying a quantity of money, such as spend, cost, or a budget ceiling. Additive only among values sharing a currency and a unit encoding." ;
    dcterms:description "The property spine's counterpart of the MonetaryValue class. Provider wire encodings differ between minor units, micros, and decimal strings; the field beneath this property keeps its wire encoding, and the observation model carries the canonicalised amount." .

:ratioValue
    a rdf:Property ;
    rdfs:subPropertyOf :metricValue ;
    rdfs:label "ratio value" ;
    rdfs:comment "A provider field carrying a derived quotient, such as click-through rate or frequency. Not additive under any circumstances." ;
    dcterms:description "The property spine's counterpart of the RatioValue class. A consumer that needs a ratio over an aggregate recomputes it from the additive fields; averaging provider-supplied ratios is wrong whenever the denominators differ." .

:costRateValue
    a rdf:Property ;
    rdfs:subPropertyOf :metricValue ;
    rdfs:label "cost rate value" ;
    rdfs:comment "A provider field carrying money per counted unit, such as cost per click or cost per thousand impressions. Not additive, and not comparable across currencies." ;
    dcterms:description "The property spine's counterpart of the CostRateValue class: a rate like a ratio, and currency-denominated like money, so it is summable under neither reading." .


# --- Wire encoding -----------------------------------------------------------

:WireEncoding
    a rdfs:Class ;
    rdfs:label "wire encoding" ;
    rdfs:comment "The relation between the literal a provider field carries and the canonical magnitude an observation records." ;
    dcterms:description "A field beneath the property spine keeps the literal its API sends, so the same quantity of money arrives as micros from one provider and as a decimal in major units from another. Nothing in the literal says which, and both readings are plausible for the same number: 1000000 is either one unit of currency or a million of them. Naming the encoding on the field is what allows the canonical magnitude to be derived rather than guessed." .

:lowersTo
    a rdf:Property ;
    rdfs:label "lowers to" ;
    rdfs:comment "The datatype a literal in this encoding carries once lowered." ;
    rdfs:domain :WireEncoding ;
    rdfs:range rdfs:Datatype ;
    dcterms:description "A reader divides the literal by :lowersBy and reads the result as this datatype. Monetary and counted quantities lower to a decimal. A quantity counting time from an epoch lowers to an instant, which no division alone reaches." .

:lowersBy
    a rdf:Property ;
    rdfs:label "lowers by" ;
    rdfs:comment "The divisor carrying a literal in this encoding to the canonical magnitude." ;
    rdfs:domain :WireEncoding ;
    rdfs:range xsd:decimal ;
    dcterms:description "Stated on the encoding rather than on each field, because the divisor is a fact about the encoding. An encoding whose divisor depends on the value's currency states no divisor here and sets :lowersByCurrencyExponent instead." .

:lowersByCurrencyExponent
    a rdf:Property ;
    rdfs:label "lowers by currency exponent" ;
    rdfs:comment "Whether the divisor is ten raised to the ISO 4217 exponent of the value's currency." ;
    rdfs:domain :WireEncoding ;
    rdfs:range xsd:boolean ;
    dcterms:description "True for an encoding counting a currency's minor unit, where the divisor is one hundred for most currencies and one for those ISO 4217 gives an exponent of zero. A reader must resolve the currency through :currencySource before dividing." .

:MajorUnits
    a :WireEncoding ;
    :lowersTo xsd:decimal ;
    rdfs:label "major units" ;
    rdfs:comment "A quantity already in the currency's major unit, such as 12.34 for twelve units and thirty-four subunits. Lowered to the canonical magnitude unchanged." ;
    :lowersBy 1.0 ;
    :lowersByCurrencyExponent false .

:MinorUnits
    a :WireEncoding ;
    :lowersTo xsd:decimal ;
    rdfs:label "minor units" ;
    :lowersByCurrencyExponent true ;
    rdfs:comment "An integer count of the currency's minor unit, such as 1234 for twelve units and thirty-four subunits." ;
    dcterms:description "Lowered by dividing by ten raised to the exponent ISO 4217 assigns the currency. That exponent is two for most currencies and zero for several, so a fixed divisor of one hundred is wrong for them and the currency has to be read before the division." .

:Micros
    a :WireEncoding ;
    :lowersTo xsd:decimal ;
    rdfs:label "micros" ;
    :lowersBy 1000000.0 ;
    :lowersByCurrencyExponent false ;
    rdfs:comment "An integer count of millionths of the currency's major unit, such as 12340000 for twelve units and thirty-four subunits. Lowered by dividing by one million." .

:CountOccurrences
    a :WireEncoding ;
    :lowersTo xsd:decimal ;
    rdfs:label "count occurrences" ;
    :lowersBy 1.0 ;
    :lowersByCurrencyExponent false ;
    rdfs:comment "A quantity counting occurrences rather than money, lowered to a decimal so that an apportioned fraction survives the conversion." .

:UnitFraction
    a :WireEncoding ;
    :lowersTo xsd:decimal ;
    rdfs:label "unit fraction" ;
    :lowersBy 1.0 ;
    :lowersByCurrencyExponent false ;
    rdfs:comment "A dimensionless quotient carried as a fraction of one, such as 0.1 for one tenth." ;
    dcterms:description "Read as it stands. A provider states this unit by reporting the value between bounds that are fractions of one, and a quotient a provider scales by one hundred is a different unit that this term does not describe." .

:EpochSeconds
    a :WireEncoding ;
    :lowersTo xsd:dateTime ;
    :lowersBy 1.0 ;
    rdfs:label "epoch seconds" ;
    rdfs:comment "A count of seconds since 1970-01-01T00:00:00Z, such as 1700000000 for 2023-11-14T22:13:20Z." ;
    dcterms:description "Read as an instant in UTC. A provider states this unit in the field's own documentation, and a field that says only that it carries a Unix timestamp states no unit and is left unencoded." .

:EpochMilliseconds
    a :WireEncoding ;
    :lowersTo xsd:dateTime ;
    :lowersBy 1000.0 ;
    rdfs:label "epoch milliseconds" ;
    rdfs:comment "A count of milliseconds since 1970-01-01T00:00:00Z, such as 1700000000000 for 2023-11-14T22:13:20Z." ;
    dcterms:description "Divided by one thousand and read as an instant in UTC. A count of milliseconds and a count of seconds differ by three orders of magnitude, and both are plausible integers for a recent instant, so the unit cannot be recovered from the literal." .

:wireEncoding
    a rdf:Property ;
    rdfs:label "wire encoding" ;
    rdfs:comment "The encoding of the literal a provider field carries." ;
    rdfs:domain rdf:Property ;
    rdfs:range :WireEncoding ;
    dcterms:description "Stated on the provider field rather than on the observation, because the encoding is a fact about the source API and does not vary between rows. The OWL addendum types it as an annotation property so that a statement whose subject is itself a property stays inside OWL DL." .

:currencySource
    a rdf:Property ;
    rdfs:label "currency source" ;
    rdfs:comment "The provider field carrying the ISO 4217 code that applies to a monetary field's value." ;
    rdfs:domain rdf:Property ;
    rdfs:range rdf:Property ;
    dcterms:description "A monetary field and its currency arrive as siblings on one provider record far more often than as a single resource. Naming the sibling is what lets a monetary amount be assembled from them, and the amount class requires both because neither is meaningful alone. A monetary field that names no currency source cannot be compared with any other." .


# --- Grain individuals -------------------------------------------------------

:AccountGrain
    a :ObservationGrain ;
    rdfs:label "account grain" ;
    rdfs:comment "The observation's subject is an advertiser account." .

:CampaignGrain
    a :ObservationGrain ;
    rdfs:label "campaign grain" ;
    rdfs:comment "The observation's subject is a campaign." .

:AdGroupGrain
    a :ObservationGrain ;
    rdfs:label "ad group grain" ;
    rdfs:comment "The observation's subject is the targeting and bidding tier below a campaign." .

:AdGrain
    a :ObservationGrain ;
    rdfs:label "ad grain" ;
    rdfs:comment "The observation's subject is an individual ad." .


# --- Metric kind scheme ------------------------------------------------------


:rateDenominatorMetric
    a rdf:Property ;
    rdfs:label "rate denominator metric" ;
    rdfs:comment "The metric kind a derived kind divides by, so a rate states what it is per." ;
    dcterms:description "Without it, cost per mille and cost per thousand reached are indistinguishable declarations of a quotient, and a consumer cannot tell whether the denominator counted renderings or people. Stated on the kind rather than on each value, because it is a fact about the metric and not about any one figure." ;
    rdfs:domain :MetricKind ;
    rdfs:range :MetricKind .


:MetricKindScheme
    a skos:ConceptScheme ;
    rdfs:label "metric kind scheme" ;
    rdfs:comment "Controlled vocabulary of the phenomena advertising observations measure." ;
    skos:prefLabel "Advertising metric kinds" .

:impressions
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "impressions" ;
    rdfs:comment "Number of times an ad was rendered." ;
    skos:definition "A count of ad renderings within the reporting window." .

:clicks
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "clicks" ;
    rdfs:comment "Number of times an ad was clicked." ;
    skos:definition "A count of click interactions within the reporting window." .

:spend
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "spend" ;
    rdfs:comment "Amount of money charged for delivery." ;
    skos:definition "A monetary quantity charged to the advertiser within the reporting window." .

:conversions
    a :AttributedMetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "conversions" ;
    rdfs:comment "Number of outcomes credited to advertising under the observation's attribution basis." ;
    skos:definition "A count, possibly fractional, of credited outcomes within the reporting window." .

:conversionValue
    a :AttributedMetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "conversion value" ;
    rdfs:comment "Monetary worth of the outcomes credited to advertising." ;
    skos:definition "A monetary quantity attributed to credited outcomes within the reporting window." .

:reach
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "reach" ;
    rdfs:comment "Number of distinct people who saw an ad." ;
    skos:definition "A count of unique individuals reached within the reporting window. Not additive across windows." .

:videoView
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "video view" ;
    rdfs:comment "Number of times video creative was watched to a provider-defined threshold." ;
    skos:definition "A count of qualifying video views within the reporting window." .

:engagement
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    rdfs:label "engagement metric" ;
    rdfs:comment "Number of interactions with an ad other than clicks." ;
    skos:definition "A count of non-click interactions within the reporting window." .

:frequency
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :reach ;
    rdfs:label "frequency" ;
    rdfs:comment "Average number of times each reached person saw an ad. Derived from impressions and reach, and not additive." ;
    skos:definition "A ratio of impressions to reach over the reporting window." .

:costPerMille
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :impressions ;
    rdfs:label "cost per mille" ;
    rdfs:comment "Spend divided by impressions, scaled to a thousand. Derived and not additive." ;
    skos:definition "A ratio of spend to a thousand impressions over the reporting window." .

:clickThroughRate
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :impressions ;
    rdfs:label "click-through rate" ;
    rdfs:comment "Clicks divided by impressions, expressed canonically as a fractional quotient rather than percentage points. Derived and not additive." ;
    skos:definition "A ratio of clicks to impressions over the reporting window; a provider value of 2.12 percent is recorded canonically as 0.0212." .

:costPerThousandReached
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :reach ;
    rdfs:label "cost per thousand reached" ;
    rdfs:comment "Spend divided by reach, scaled to a thousand. Distinct from cost per mille because reach counts people and impressions count renderings." ;
    skos:definition "A ratio of spend to a thousand people reached over the reporting window." .

:costPerClick
    a :MetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :clicks ;
    rdfs:label "cost per click" ;
    rdfs:comment "Spend divided by clicks. Derived and not additive." ;
    skos:definition "A ratio of spend to clicks over the reporting window." .

:returnOnAdSpend
    a :AttributedMetricKind, skos:Concept ;
    skos:inScheme :MetricKindScheme ;
    :rateDenominatorMetric :spend ;
    rdfs:label "return on ad spend" ;
    rdfs:comment "Conversion value divided by spend. Derived and not additive." ;
    skos:definition "A ratio of attributed conversion value to spend over the reporting window." .


# --- Channel scheme ----------------------------------------------------------

:ChannelScheme
    a skos:ConceptScheme ;
    rdfs:label "channel scheme" ;
    rdfs:comment "Controlled vocabulary of platforms an advertiser buys through." ;
    skos:prefLabel "Advertising channels" .

:metaChannel
    a :Channel, skos:Concept ;
    skos:inScheme :ChannelScheme ;
    rdfs:label "Meta" ;
    rdfs:comment "Buying through Meta advertising." .

:googleAdsChannel
    a :Channel, skos:Concept ;
    skos:inScheme :ChannelScheme ;
    rdfs:label "Google Ads" ;
    rdfs:comment "Buying through Google Ads." .

:linkedinChannel
    a :Channel, skos:Concept ;
    skos:inScheme :ChannelScheme ;
    rdfs:label "LinkedIn" ;
    rdfs:comment "Buying through LinkedIn advertising." .

:pinterestChannel
    a :Channel, skos:Concept ;
    skos:inScheme :ChannelScheme ;
    rdfs:label "Pinterest" ;
    rdfs:comment "Buying through Pinterest advertising." .

:tiktokChannel
    a :Channel, skos:Concept ;
    skos:inScheme :ChannelScheme ;
    rdfs:label "TikTok" ;
    rdfs:comment "Buying through TikTok advertising. Present because measurement platforms report spend against it even where no direct integration exists." .


# --- Credited interaction scheme ---------------------------------------------

:CreditedInteractionScheme
    a skos:ConceptScheme ;
    rdfs:label "credited interaction scheme" ;
    rdfs:comment "Controlled vocabulary of interaction kinds an attribution basis credits." ;
    skos:prefLabel "Credited interactions" .

:clickThroughCredit
    a :CreditedInteraction, skos:Concept ;
    skos:inScheme :CreditedInteractionScheme ;
    rdfs:label "click-through" ;
    rdfs:comment "An interaction in which the person clicked the ad before the credited outcome." .

:viewThroughCredit
    a :CreditedInteraction, skos:Concept ;
    skos:inScheme :CreditedInteractionScheme ;
    rdfs:label "view-through" ;
    rdfs:comment "Credit is assigned on an impression alone, with no click. View-through figures are typically far larger than click-through ones for the same campaign." .

:engagedViewCredit
    a :CreditedInteraction, skos:Concept ;
    skos:inScheme :CreditedInteractionScheme ;
    rdfs:label "engaged view" ;
    rdfs:comment "Credit is assigned where the person watched to a provider-defined threshold without clicking." .


# --- Attribution model scheme ------------------------------------------------

:AttributionModelScheme
    a skos:ConceptScheme ;
    rdfs:label "attribution model scheme" ;
    rdfs:comment "Controlled vocabulary of credit-assignment rules." ;
    skos:prefLabel "Attribution models" .

:lastClickModel
    a :AttributionModel, skos:Concept ;
    skos:inScheme :AttributionModelScheme ;
    rdfs:label "last click" ;
    rdfs:comment "All credit assigned to the final click before the outcome." .

:firstClickModel
    a :AttributionModel, skos:Concept ;
    skos:inScheme :AttributionModelScheme ;
    rdfs:label "first click" ;
    rdfs:comment "All credit assigned to the first click in the path." .

:linearModel
    a :AttributionModel, skos:Concept ;
    skos:inScheme :AttributionModelScheme ;
    rdfs:label "linear" ;
    rdfs:comment "Credit divided evenly across all interactions in the path." .

:providerProprietaryModel
    a :AttributionModel, skos:Concept ;
    skos:inScheme :AttributionModelScheme ;
    rdfs:label "provider proprietary" ;
    rdfs:comment "A provider's undisclosed model. Distinct per provider: two proprietary models are never interchangeable, and an observation using one must record which provider's rule applied." .


# --- Breakdown dimension scheme ----------------------------------------------
#
# Derived from the dimensions providers actually document, not from anticipated
# ones. Provider profiles extend this scheme; they do not replace it.

:BreakdownDimensionScheme
    a skos:ConceptScheme ;
    rdfs:label "breakdown dimension scheme" ;
    rdfs:comment "Controlled vocabulary of axes along which advertising measures are partitioned." ;
    skos:prefLabel "Breakdown dimensions" .

:publisherPlatformDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "publisher platform dimension" ;
    skos:prefLabel "publisher platform" ;
    rdfs:comment "Partition by the property the ad was delivered on. Values are instances of PublisherPlatform." .

:placementDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "placement dimension" ;
    skos:prefLabel "placement" ;
    rdfs:comment "Partition by the position within a publisher property. Values are instances of Placement." .

:deviceDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "device dimension" ;
    skos:prefLabel "device" ;
    rdfs:comment "Partition by the class of device the ad was rendered on." .

:countryDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "country dimension" ;
    skos:prefLabel "country" ;
    rdfs:comment "Partition by the country the impression was served in." .

:regionDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "region dimension" ;
    skos:prefLabel "region" ;
    rdfs:comment "Partition by a sub-national region. Region naming is provider-specific and does not align across platforms without a crosswalk." .

:marketAreaDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "market area dimension" ;
    skos:prefLabel "market area" ;
    rdfs:comment "Partition by a designated media market. Market definitions are licensed and platform-specific." .

:ageDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "age dimension" ;
    skos:prefLabel "age" ;
    rdfs:comment "Partition by an age band. Band boundaries are provider-specific and are not interchangeable across platforms." .

:genderDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "gender dimension" ;
    skos:prefLabel "gender" ;
    rdfs:comment "Partition by a reported gender category, including an unknown category that providers populate heavily." .

:exposureCountDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "exposure count dimension" ;
    skos:prefLabel "exposure count" ;
    rdfs:comment "Partition by how many times a person was exposed, reported as buckets such as one, several, or many. The same word names a measure elsewhere in this module, and the two are different things: one counts exposures, the other groups people by their exposure count." .

:audienceSegmentDimension
    a :BreakdownDimension, skos:Concept ;
    skos:inScheme :BreakdownDimensionScheme ;
    rdfs:label "audience segment dimension" ;
    skos:prefLabel "audience segment" ;
    rdfs:comment "Partition by a targeting or audience segment." .


# --- Publisher platform scheme -----------------------------------------------

:PublisherPlatformScheme
    a skos:ConceptScheme ;
    rdfs:label "publisher platform scheme" ;
    rdfs:comment "Properties advertising is delivered on. Extended by provider profiles." ;
    skos:prefLabel "Publisher platforms" .

:facebookPlatform
    a :PublisherPlatform, skos:Concept ;
    skos:inScheme :PublisherPlatformScheme ;
    rdfs:label "Facebook" ;
    rdfs:comment "Delivery on Facebook properties." .

:instagramPlatform
    a :PublisherPlatform, skos:Concept ;
    skos:inScheme :PublisherPlatformScheme ;
    rdfs:label "Instagram" ;
    rdfs:comment "Delivery on Instagram properties." .

:messengerPlatform
    a :PublisherPlatform, skos:Concept ;
    skos:inScheme :PublisherPlatformScheme ;
    rdfs:label "Messenger" ;
    rdfs:comment "Delivery in Messenger." .

:audienceNetworkPlatform
    a :PublisherPlatform, skos:Concept ;
    skos:inScheme :PublisherPlatformScheme ;
    rdfs:label "audience network" ;
    rdfs:comment "Delivery on third-party inventory syndicated by the buying platform." .

:unknownPlatform
    a :PublisherPlatform, skos:Concept ;
    skos:inScheme :PublisherPlatformScheme ;
    rdfs:label "unknown platform" ;
    rdfs:comment "The platform was not reported. Providers populate this materially, and dropping such rows silently understates any platform-partitioned total." .


# --- Placement scheme --------------------------------------------------------
#
# Positions providers actually report. A joined publisher-and-position value
# lowers to one breakdown on each dimension rather than a single composite.

:PlacementScheme
    a skos:ConceptScheme ;
    rdfs:label "placement scheme" ;
    rdfs:comment "Cross-provider anchors for delivery surfaces. Provider profiles extend this scheme with their own surfaces rather than redefining these." ;
    skos:prefLabel "Advertising placements" .

:feedPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "feed" ;
    rdfs:comment "An in-feed surface within a social or content stream." .

:storiesPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "stories" ;
    rdfs:comment "A full-screen ephemeral surface between organic story cards." .

:reelsPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "reels" ;
    rdfs:comment "A position within a short-form vertical video surface." .

:marketplacePlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "marketplace" ;
    rdfs:comment "A position within a commerce listing surface." .

:sidebarPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "sidebar" ;
    rdfs:comment "A position in a column beside the main content, reported by some providers as a right-hand column." .

:inStreamVideoPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "in-stream video" ;
    rdfs:comment "A position inside video playback." .

:videoFeedPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "video feed" ;
    rdfs:comment "A position within a browsable video surface, distinct from playback itself." .

:searchResultsPlacement
    a :PlacementSurface, skos:Concept ;
    skos:inScheme :PlacementScheme ;
    rdfs:label "search results" ;
    rdfs:comment "A surface on a search engine results page." .


# --- Spine comparability -----------------------------------------------------

:SpineComparability
    a rdfs:Class ;
    rdfs:label "spine comparability" ;
    rdfs:comment "The datatype that values beneath one shared term compare as, whatever datatype each provider sends." ;
    dcterms:description "Providers disagree about the literal type of the same quantity. One sends a price as a decimal and another as text, one sends a creation time as a datetime and another as a count of seconds. The shared term is what a reader queries, so the reader needs one answer for how to compare its values. Stated as a resource of this module rather than as an axiom on the shared term, because the shared term belongs to another vocabulary." .

:spineTerm
    a rdf:Property ;
    rdfs:label "spine term" ;
    rdfs:comment "The shared term whose values this resource describes." ;
    rdfs:domain :SpineComparability ;
    rdfs:range rdf:Property .

:comparableAs
    a rdf:Property ;
    rdfs:label "comparable as" ;
    rdfs:comment "The datatype a reader casts values to before comparing them across providers." ;
    rdfs:domain :SpineComparability ;
    rdfs:range rdfs:Datatype .

:identifierComparability
    a :SpineComparability ;
    rdfs:label "identifier comparability" ;
    rdfs:comment "An identifier is an opaque token. A provider sending it as a number does not make it arithmetic." ;
    :spineTerm <https://schema.org/identifier> ;
    :comparableAs xsd:string .

:dateCreatedComparability
    a :SpineComparability ;
    rdfs:label "dateCreated comparability" ;
    rdfs:comment "An instant, whichever of a date, a datetime or a count from an epoch the provider sends." ;
    :spineTerm <https://schema.org/dateCreated> ;
    :comparableAs xsd:dateTime .

:dateModifiedComparability
    a :SpineComparability ;
    rdfs:label "dateModified comparability" ;
    rdfs:comment "An instant, whichever of a date, a datetime or a count from an epoch the provider sends." ;
    :spineTerm <https://schema.org/dateModified> ;
    :comparableAs xsd:dateTime .

:priceComparability
    a :SpineComparability ;
    rdfs:label "price comparability" ;
    rdfs:comment "A monetary magnitude. A provider sending it as text still sends a number." ;
    :spineTerm <https://schema.org/price> ;
    :comparableAs xsd:decimal .

:valueComparability
    a :SpineComparability ;
    rdfs:label "value comparability" ;
    rdfs:comment "A measured magnitude. A provider sending it as text still sends a number." ;
    :spineTerm <https://schema.org/value> ;
    :comparableAs xsd:decimal .

:startDateComparability
    a :SpineComparability ;
    rdfs:label "startDate comparability" ;
    rdfs:comment "An instant opening a range." ;
    :spineTerm <https://schema.org/startDate> ;
    :comparableAs xsd:dateTime .

:endDateComparability
    a :SpineComparability ;
    rdfs:label "endDate comparability" ;
    rdfs:comment "An instant closing a range." ;
    :spineTerm <https://schema.org/endDate> ;
    :comparableAs xsd:dateTime .

:heightComparability
    a :SpineComparability ;
    rdfs:label "height comparability" ;
    rdfs:comment "A spatial magnitude." ;
    :spineTerm <https://schema.org/height> ;
    :comparableAs xsd:decimal .

:widthComparability
    a :SpineComparability ;
    rdfs:label "width comparability" ;
    rdfs:comment "A spatial magnitude." ;
    :spineTerm <https://schema.org/width> ;
    :comparableAs xsd:decimal .

:durationComparability
    a :SpineComparability ;
    rdfs:label "duration comparability" ;
    rdfs:comment "A length of time in seconds, whichever of a number or an ISO 8601 string the provider sends." ;
    :spineTerm <https://schema.org/duration> ;
    :comparableAs xsd:decimal .

:monetaryValueComparability
    a :SpineComparability ;
    rdfs:label "monetaryValue comparability" ;
    rdfs:comment "A monetary magnitude, lowered by the field's wire encoding before comparison." ;
    :spineTerm <https://ontology.inferal.com/modules/advertising-measurement/monetaryValue> ;
    :comparableAs xsd:decimal .

:orderNumberComparability
    a :SpineComparability ;
    rdfs:label "orderNumber comparability" ;
    rdfs:comment "An order reference is an opaque token." ;
    :spineTerm <https://schema.org/orderNumber> ;
    :comparableAs xsd:string .

:positionComparability
    a :SpineComparability ;
    rdfs:label "position comparability" ;
    rdfs:comment "An ordinal position." ;
    :spineTerm <https://schema.org/position> ;
    :comparableAs xsd:decimal .

:availabilityComparability
    a :SpineComparability ;
    rdfs:label "availability comparability" ;
    rdfs:comment "A yes or no, whichever of a boolean or a token the provider sends." ;
    :spineTerm <https://schema.org/availability> ;
    :comparableAs xsd:boolean .

:orderDateComparability
    a :SpineComparability ;
    rdfs:label "orderDate comparability" ;
    rdfs:comment "An instant." ;
    :spineTerm <https://schema.org/orderDate> ;
    :comparableAs xsd:dateTime .

:weightComparability
    a :SpineComparability ;
    rdfs:label "weight comparability" ;
    rdfs:comment "A mass magnitude." ;
    :spineTerm <https://schema.org/weight> ;
    :comparableAs xsd:decimal .

:aggregateRatingComparability
    a :SpineComparability ;
    rdfs:label "aggregateRating comparability" ;
    rdfs:comment "A rating magnitude." ;
    :spineTerm <https://schema.org/aggregateRating> ;
    :comparableAs xsd:decimal .

:validThroughComparability
    a :SpineComparability ;
    rdfs:label "validThrough comparability" ;
    rdfs:comment "An instant closing a validity range." ;
    :spineTerm <https://schema.org/validThrough> ;
    :comparableAs xsd:dateTime .

:ratingValueComparability
    a :SpineComparability ;
    rdfs:label "ratingValue comparability" ;
    rdfs:comment "A rating magnitude." ;
    :spineTerm <https://schema.org/ratingValue> ;
    :comparableAs xsd:decimal .

:startTimeComparability
    a :SpineComparability ;
    rdfs:label "startTime comparability" ;
    rdfs:comment "An instant." ;
    :spineTerm <https://schema.org/startTime> ;
    :comparableAs xsd:dateTime .

:amountComparability
    a :SpineComparability ;
    rdfs:label "amount comparability" ;
    rdfs:comment "A magnitude." ;
    :spineTerm <https://schema.org/amount> ;
    :comparableAs xsd:decimal .
