{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.nocodeexport.com/research/export-reliability-methodology-v1.json",
  "title": "NoCodeExport website export reliability observation",
  "description": "Version 1.0.0 schema for a de-identified prospective benchmark observation. This file contains methodology and field definitions only; it contains no benchmark results or customer observations.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "instrumentationVersion",
    "observationKey",
    "siteCohortKey",
    "cohortDay",
    "exportType",
    "platform",
    "platformConfidence",
    "source",
    "assetStrategy",
    "outcome",
    "artifactReady",
    "deliveryPath",
    "deliveryOutcome",
    "pagesRequested",
    "pagesAttempted",
    "pagesExported",
    "pagesFailed",
    "pagesDegraded",
    "assetsAttempted",
    "assetsDownloaded",
    "assetErrors",
    "durationMs",
    "artifactSizeBytes",
    "failureCategory",
    "feedbackWorked",
    "feedbackIssues"
  ],
  "properties": {
    "instrumentationVersion": { "const": 1 },
    "observationKey": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$",
      "description": "Domain-separated keyed identifier for one attempt; it contains no raw export ID."
    },
    "siteCohortKey": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$",
      "description": "Separately keyed identifier derived from the normalized hostname for 30-day cohort grouping."
    },
    "cohortDay": {
      "type": "string",
      "format": "date",
      "description": "UTC acceptance day. Exact task timestamps are not retained in the benchmark table."
    },
    "exportType": { "enum": ["single", "full"] },
    "platform": {
      "enum": ["framer", "webflow", "wix", "squarespace", "wordpress", "elementor", "nextjs", "unknown", "other"]
    },
    "platformConfidence": {
      "type": ["integer", "null"],
      "minimum": 0,
      "maximum": 100
    },
    "source": { "enum": ["web", "api", "scheduled", "unknown"] },
    "assetStrategy": { "enum": ["hotlinked", "localized", "mixed", "not_applicable"] },
    "outcome": {
      "enum": ["started", "success", "failed", "canceled", "timed_out"],
      "description": "The start row is inserted before expensive work. A reconciler resolves stale started rows so crashes and hard timeouts remain in the denominator."
    },
    "artifactReady": {
      "type": "boolean",
      "description": "True only when the export completed and a downloadable artifact was stored."
    },
    "deliveryPath": { "enum": ["download", "github", "netlify", "other", "not_requested"] },
    "deliveryOutcome": { "enum": ["succeeded", "failed", "not_requested", "not_reached"] },
    "pagesRequested": { "type": ["integer", "null"], "minimum": 0 },
    "pagesAttempted": { "type": ["integer", "null"], "minimum": 0 },
    "pagesExported": { "type": ["integer", "null"], "minimum": 0 },
    "pagesFailed": { "type": ["integer", "null"], "minimum": 0 },
    "pagesDegraded": { "type": ["integer", "null"], "minimum": 0 },
    "assetsAttempted": { "type": ["integer", "null"], "minimum": 0 },
    "assetsDownloaded": { "type": ["integer", "null"], "minimum": 0 },
    "assetErrors": { "type": ["integer", "null"], "minimum": 0 },
    "durationMs": {
      "type": ["integer", "null"],
      "minimum": 0,
      "description": "Elapsed time from the accepted task start to the observed terminal transition."
    },
    "artifactSizeBytes": { "type": ["integer", "null"], "minimum": 0 },
    "failureCategory": {
      "type": ["string", "null"],
      "enum": [
        "input_or_access",
        "crawl_or_discovery",
        "browser_rendering",
        "page_processing",
        "asset_retrieval",
        "packaging_or_storage",
        "delivery_integration",
        "timeout_or_cancellation",
        "unclassified_internal",
        null
      ]
    },
    "feedbackWorked": {
      "type": ["boolean", "null"],
      "description": "Optional normalized user verdict. Comments are never copied into benchmark telemetry."
    },
    "feedbackIssues": {
      "type": "array",
      "uniqueItems": true,
      "items": { "enum": ["animations", "assets", "interactions", "forms", "layout", "branding", "other"] }
    }
  },
  "x-study": {
    "methodologyVersion": "1.0.0",
    "publishedAt": "2026-08-31",
    "status": "collection_in_progress",
    "collectionWindow": {
      "start": "2026-09-15T02:07:00Z",
      "end": "2026-12-13T23:59:59Z",
      "days": 90,
      "note": "Opened when the secret-gated instrumentation, reconciliation task and health check went live in production; the close date will not move."
    },
    "collectionGaps": [
      {
        "start": "2026-09-28T15:08:00Z",
        "end": "2026-10-16T19:38:00Z",
        "disclosedAt": "2026-10-16",
        "cause": "Production exports moved to a new dispatch path that did not carry the benchmark switch, so no attempt started in this interval was recorded.",
        "treatment": "Excluded, not imputed or reconstructed from operational records; the window, its end date and all definitions are unchanged."
      }
    ],
    "resultsPublished": false,
    "activationRequirements": [
      "production database migration applied",
      "EXPORT_BENCHMARK_ENABLED=true configured in every production environment that runs or dispatches exports (the site Worker and Trigger.dev)",
      "one stable 32-byte-or-longer HMAC secret configured in the site Worker and Trigger.dev",
      "web, API, and scheduled production callsites explicitly opted in",
      "start, terminal, feedback, and stale-run reconciliation tasks deployed",
      "collection health check passing"
    ],
    "cohort": {
      "design": "prospective",
      "minimumDays": 60,
      "maximumDays": 90,
      "primaryUnit": "one deterministic observation from the earliest eligible UTC day per pseudonymous normalized hostname in each rolling 30-day cluster",
      "sameDayTieBreak": "opaque observationKey order; raw hostnames and exact timestamps are not retained",
      "retryPolicy": "automatic retries keep the same observationKey; later user attempts remain separate observations",
      "eligible": "production exports of publicly reachable sites that pass input validation, are claimed by the export task, and carry an explicit production benchmark context",
      "excluded": [
        "internal tests",
        "staff-triggered diagnostics",
        "synthetic monitoring",
        "direct task replays without production context",
        "repair-only delivery replays"
      ]
    },
    "retentionBiasControl": "The export claim and de-identified started row commit atomically before expensive work. Terminal compare-and-set updates preserve retries and never create terminal-only rows. Matched stale starts are reconciled after the task deadline; unmatched rows wait until the UTC day closes plus the deadline and grace interval. Historical records are not used for the headline result.",
    "primaryMetric": "artifact-ready completion: successful terminal outcome plus a stored downloadable artifact, divided by all eligible primary attempts",
    "lowCellPolicy": {
      "minimumDenominator": 10,
      "complementarySuppression": true,
      "smallGroupsMayBeCombinedAsOther": true
    },
    "privacy": {
      "publicObservationRows": false,
      "observationRetentionDays": 180,
      "postRetentionData": "Only validated, disclosure-controlled aggregate results and the versioned methodology are retained after observation rows are purged.",
      "excludedFromBenchmarkStorage": [
        "domains and hostnames",
        "full URLs and page paths",
        "exact task timestamps",
        "account, project, user, and run identifiers",
        "authentication data and provider coordinates",
        "raw errors and logs",
        "customer comments and artifacts"
      ]
    },
    "publication": "Aggregate results will replace the pre-collection status at /blog/website-export-reliability-benchmark after the prospective window closes and validation is complete."
  }
}
