{
  "type": "object",
  "required": ["telemetryId", "searchPageRegexp", "queryParamName"],
  "properties": {
    "telemetryId": {
      "type": "string",
      "title": "Telemetry Id",
      "description": "The telemetry identifier for the provider.",
      "pattern": "^[a-z0-9-._]*$"
    },
    "searchPageRegexp": {
      "type": "string",
      "title": "Search Page Regular Expression",
      "description": "A regular expression which matches the search page of the provider."
    },
    "queryParamName": {
      "type": "string",
      "title": "Search Query Parameter Name",
      "description": "The name of the query parameter for the user's search string."
    },
    "codeParamName": {
      "type": "string",
      "title": "Partner Code Parameter Name",
      "description": "The name of the query parameter for the partner code."
    },
    "taggedCodes": {
      "type": "array",
      "title": "Partner Codes",
      "description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as tagged.",
      "items": {
        "type": "string",
        "pattern": "^[a-zA-Z0-9-._]*$"
      }
    },
    "expectedOrganicCodes": {
      "type": "array",
      "title": "Expected Organic Codes",
      "description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as organic:none which means the user has done a search through the search engine's website rather than through SAP.",
      "items": {
        "type": "string",
        "pattern": "^[a-zA-Z0-9-._]*$"
      }
    },
    "organicCodes": {
      "type": "array",
      "title": "Organic Codes",
      "description": "An array of partner codes to match against the parameters in the url. Matching these codes will report the SERP as organic:<partner code>, which means the search was performed organically rather than through a SAP.",
      "items": {
        "type": "string",
        "pattern": "^[a-zA-Z0-9-._]*$"
      }
    },
    "followOnParamNames": {
      "type": "array",
      "title": "Follow-on Search Parameter Names",
      "description": "An array of query parameter names that are used when a follow-on search occurs.",
      "items": {
        "type": "string",
        "pattern": "^[a-z0-9-._]*$"
      }
    },
    "followOnCookies": {
      "type": "array",
      "title": "Follow-on Cookies",
      "description": "An array of cookie details that are used to identify follow-on searches.",
      "items": {
        "type": "object",
        "properties": {
          "extraCodeParamName": {
            "type": "string",
            "description": "The query parameter name in the URL that indicates this might be a follow-on search.",
            "pattern": "^[a-z0-9-._]*$"
          },
          "extraCodePrefixes": {
            "type": "array",
            "description": "Possible values for the query parameter in the URL that indicates this might be a follow-on search.",
            "items": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9-._]*$"
            }
          },
          "host": {
            "type": "string",
            "description": "The hostname on which the cookie is stored.",
            "pattern": "^[a-z0-9-._]*$"
          },
          "name": {
            "type": "string",
            "description": "The name of the cookie to check.",
            "pattern": "^[a-zA-Z0-9-._]*$"
          },
          "codeParamName": {
            "type": "string",
            "description": "The name of parameter within the cookie.",
            "pattern": "^[a-zA-Z0-9-._]*$"
          }
        }
      }
    },
    "extraAdServersRegexps": {
      "type": "array",
      "title": "Extra Ad Server Regular Expressions",
      "description": "An array of regular expressions that match URLs of potential ad servers.",
      "items": {
        "type": "string"
      }
    },
    "adServerAttributes": {
      "type": "array",
      "title": "Ad Server Attributes",
      "description": "An array of strings that potentially match data-attribute keys of anchors.",
      "items": {
        "type": "string"
      }
    },
    "components": {
      "type": "array",
      "title": "Components",
      "description": "An array of components that could be on the SERP.",
      "items": {
        "required": ["type"],
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "ad_carousel",
              "ad_image_row",
              "ad_link",
              "ad_sitelink",
              "ad_sidebar",
              "incontent_searchbox",
              "refined_search_buttons",
              "shopping_tab"
            ],
            "description": "The type of component the anchor or DOM element should belong to."
          },
          "included": {
            "type": "object",
            "description": "Conditions that should be fulfilled.",
            "properties": {
              "parent": {
                "title": "Parent",
                "description": "The DOM element that should only contain elements applicable to a single component type.",
                "type": "object",
                "properties": {
                  "selector": {
                    "description": "If topDown is true for this component, then this will be the value used in querySelectorAll(). Otherwise, it will be the value to in closest() from the context of an anchor.",
                    "type": "string"
                  }
                },
                "required": ["selector"]
              },
              "children": {
                "type": "array",
                "title": "Children",
                "description": "Child DOM elements of the parent. Optional.",
                "items": {
                  "type": "object",
                  "properties": {
                    "selector": {
                      "type": "string",
                      "description": "The selector to use querySelectorAll from the context of the parent."
                    },
                    "type": {
                      "enum": [
                        "ad_carousel",
                        "ad_image_row",
                        "ad_link",
                        "ad_sitelink",
                        "ad_sidebar",
                        "incontent_searchbox",
                        "refined_search_buttons",
                        "shopping_tab"
                      ],
                      "description": "The component type to use if this child is present."
                    },
                    "countChildren": {
                      "type": "boolean",
                      "description": "Whether we should count all instances of the child element instead of anchor links found inside of the parent. Defaults to false."
                    }
                  },
                  "required": ["selector"]
                }
              },
              "related": {
                "type": "object",
                "properties": {
                  "selector": {
                    "type": "string",
                    "description": "The selector to use querySelectorAll from the context of the parent. Any elements specified will have their click events registered and categorized as expanded unless explicitly overwritten in SearchSERPTelemetryChild."
                  }
                },
                "required": ["selector"]
              }
            },
            "required": ["parent"]
          },
          "excluded": {
            "type": "object",
            "description": "Conditions that should not be included.",
            "properties": {
              "parent": {
                "type": "object",
                "properties": {
                  "selector": {
                    "type": "string",
                    "description": "The root DOM element that shouldn't be a parent from the context of the anchor being inspected."
                  }
                },
                "required": ["selector"]
              }
            }
          },
          "default": {
            "type": "boolean",
            "description": "Whether this component should be the fallback option if a link was included in both ad-related regular expressions as well as regular expressions matching non-ad elements but couldn't be categorized. Defaults to false."
          },
          "topDown": {
            "type": "boolean",
            "description": "Whether the component should be found first by using document.querySelectorAll on the parent selector definition. Defaults to false."
          },
          "dependentRequired": {
            "topDown": ["included"]
          }
        }
      }
    },
    "nonAdsLinkRegexps": {
      "type": "array",
      "title": "Non-ads link matching regular expressions",
      "description": "An array containing known patterns that match non-ad links from a search provider.",
      "items": {
        "type": "string",
        "description": "The matching regular expression."
      }
    },
    "shoppingTab": {
      "type": "object",
      "title": "Shopping Tab",
      "properties": {
        "selector": {
          "type": "string",
          "description": "The elements on the page to inspect for the shopping tab. Should be anchor elements."
        },
        "regexp": {
          "type": "string",
          "description": "The regular expression to match against a possible shopping tab. Must be provided if using this feature."
        },
        "inspectRegexpInSERP": {
          "type": "boolean",
          "description": "Whether the regexp should be used against hrefs the selector matches against."
        }
      },
      "required": ["selector", "regexp"]
    },
    "domainExtraction": {
      "type": "object",
      "title": "Domain Extraction",
      "description": "An array of methods for extracting domains from a SERP result.",
      "properties": {
        "ads": {
          "type": "array",
          "description": "An array of methods for extracting domains from ads.",
          "items": {
            "$ref": "/schemas/extraction"
          }
        },
        "nonAds": {
          "type": "array",
          "description": "An array of methods for extracting domains from non-ads.",
          "items": {
            "$ref": "/schemas/extraction"
          }
        }
      }
    }
  },
  "$defs": {
    "extraction": {
      "$id": "/schemas/extraction",
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "selectors": {
              "type": "string",
              "description": "The query to inspect all elements on the SERP."
            },
            "method": {
              "enum": ["data-attribute"],
              "description": "The extraction method used for the query."
            },
            "options": {
              "type": "object",
              "properties": {
                "dataAttributeKey": {
                  "type": "string",
                  "description": "The data attribute key that will be looked up in order to retrieve its data attribute value."
                }
              },
              "required": ["dataAttributeKey"]
            }
          },
          "required": ["selectors", "method", "options"]
        },
        {
          "type": "object",
          "properties": {
            "selectors": {
              "type": "string",
              "description": "The query to use to inspect all elements on the SERP."
            },
            "method": {
              "enum": ["href"],
              "description": "The extraction method to use for the query."
            },
            "options": {
              "type": "object",
              "properties": {
                "queryParamKey": {
                  "type": "string",
                  "description": "The query parameter key to inspect in the href."
                }
              },
              "required": ["queryParamKey"]
            }
          },
          "required": ["selectors", "method"]
        }
      ]
    }
  }
}
