{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://opensciencelabs.org/analytics/schema.json",
  "title": "OSL public analytics report v1",
  "description": "Closed aggregate-only contract. Nulls mean unavailable, never zero. Dates are inclusive in the property timezone. Missing historical months are omitted, not imputed. generated_at is the last successful export in UTC.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "data_kind",
    "status",
    "source",
    "site",
    "hostnames",
    "timezone",
    "generated_at",
    "reporting_period",
    "history_period",
    "summary",
    "monthly_history"
  ],
  "properties": {
    "schema_version": { "const": 1 },
    "data_kind": { "enum": ["production", "fixture"] },
    "status": { "enum": ["available", "unavailable"] },
    "source": {
      "const": {
        "publisher": "Open Science Labs",
        "system": "Google Analytics 4",
        "api": "Google Analytics Data API v1beta"
      }
    },
    "site": { "const": "https://opensciencelabs.org" },
    "hostnames": {
      "type": "array",
      "uniqueItems": true,
      "items": { "type": "string", "format": "hostname" }
    },
    "timezone": { "type": ["string", "null"], "minLength": 1 },
    "generated_at": {
      "type": ["string", "null"],
      "format": "date-time",
      "pattern": "Z$"
    },
    "reporting_period": {
      "oneOf": [{ "$ref": "#/$defs/period" }, { "type": "null" }]
    },
    "history_period": {
      "oneOf": [{ "$ref": "#/$defs/period" }, { "type": "null" }]
    },
    "summary": {
      "oneOf": [
        { "type": "null" },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["pageviews", "active_users", "sessions"],
          "properties": {
            "pageviews": { "$ref": "#/$defs/count" },
            "active_users": { "$ref": "#/$defs/count" },
            "sessions": { "$ref": "#/$defs/count" }
          }
        }
      ]
    },
    "monthly_history": {
      "type": "array",
      "maxItems": 12,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["month", "start", "end", "pageviews"],
        "properties": {
          "month": {
            "type": "string",
            "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$"
          },
          "start": { "type": "string", "format": "date" },
          "end": { "type": "string", "format": "date" },
          "pageviews": { "$ref": "#/$defs/count" }
        }
      }
    }
  },
  "allOf": [
    {
      "if": { "properties": { "status": { "const": "available" } } },
      "then": {
        "properties": {
          "hostnames": { "minItems": 1 },
          "timezone": { "type": "string" },
          "generated_at": { "type": "string" },
          "reporting_period": { "$ref": "#/$defs/period" },
          "history_period": { "$ref": "#/$defs/period" },
          "summary": { "type": "object" }
        }
      },
      "else": {
        "properties": {
          "hostnames": { "maxItems": 0 },
          "timezone": { "type": "null" },
          "generated_at": { "type": "null" },
          "reporting_period": { "type": "null" },
          "history_period": { "type": "null" },
          "summary": { "type": "null" },
          "monthly_history": { "maxItems": 0 }
        }
      }
    }
  ],
  "$defs": {
    "count": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
    "period": {
      "type": "object",
      "additionalProperties": false,
      "required": ["start", "end"],
      "properties": {
        "start": { "type": "string", "format": "date" },
        "end": { "type": "string", "format": "date" }
      }
    }
  }
}
