> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.middesk.com/online-presence/web-presence/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.middesk.com/_mcp/server. # Analyze web presence > Use the Middesk Web Analysis API to evaluate a business's web presence quality through automated analysis of their website's content, domain ownership, compliance information, and other indicators. Use a Middesk website order to receive a detailed analysis of a business's web presence and evaluate a business's web presence quality. > **Note** > > Web Analysis can be ordered independently as a standalone product or alongside other Middesk products. A Verify report is not required to order Web Analysis. ## How to order Web Analysis Before you begin: * Ensure that you can authenticate against the Middesk API and create businesses. * Review the [Middesk Postman collection](https://middesk.postman.co/workspace/Middesk~7466f7e6-b402-49f6-8fef-f16c8f3f9869/collection/9313621-fbae4cfe-9d65-4ccc-b303-148ebe1d6d71) for request examples. #### Create a business and order Web Analysis Web Analysis is a subproduct of the [Website order](https://app.middesk.com/order). To create a Business with a website order, submit a [Create Business request](/api-reference/business-verification/businesses/create-a-business): **`Ruby`** ```ruby title="Ruby" require 'uri' require 'net/http' url = URI("https://api.middesk.com/v1/businesses") http = Net::HTTP.new(url.host, url.port) request = Net::HTTP::Post.new(url) request["Content-Type"] = 'application/json' request["Authorization"] = '' request.body = "{\n \"name\": \"Joe's Bakery\",\n \"addresses\": [\n\t {\n\t\t \"full_address\": \"123 Main Street, Tampa, FL 33626\"\n\t }\n ],\n \"website\": {\n\t \"url\": \"www.joesbakery.com\"\n },\n\t\"orders\": [\n\t\t{\n\t\t \"product\": \"website\",\n\t\t \"subproducts\": [\"web_analysis\"]\n\t\t}\n\t]\n}" response = http.request(request) puts response.read_body ``` **`cURL`** ```curl title="cURL" curl --request POST \ --url https://api.middesk.com/v1/businesses \ --header 'Authorization: ' \ --header 'Content-Type: application/json' \ --data '{ "name": "Joe'\''s Bakery", "addresses": [ { "full_address": "123 Main Street, Tampa, FL 33626" } ], "website": { "url": "www.joesbakery.com" }, "orders": [ { "product": "website", "subproducts": ["web_analysis"] } ] }' ``` **`Python`** ```python title="Python" import http.client conn = http.client.HTTPConnection("https://api.middesk.com") payload = "{\n \"name\": \"Joe's Bakery\",\n \"addresses\": [\n\t {\n\t\t \"full_address\": \"123 Main Street, Tampa, FL 33626\"\n\t }\n ],\n \"website\": {\n\t \"url\": \"www.joesbakery.com\"\n },\n\t\"orders\": [\n\t\t{\n\t\t \"product\": \"website\",\n\t\t \"subproducts\": [\"web_analysis\"]\n\t\t}\n\t]\n}" headers = { 'Content-Type': "application/json", 'Authorization': "" } conn.request("POST", "/v1/businesses", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8")) ``` **`JavaScript`** ```javascript title="JavaScript" const options = { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: '' }, body: '{"name":"Joe\'s Bakery","addresses":[{"full_address":"123 Main Street, Tampa, FL 33626"}],"website":{"url":"www.joesbakery.com"},"orders":[{"product":"website","subproducts":["web_analysis"]}]}' }; fetch('https://api.middesk.com/v1/businesses', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` Middesk determines which subproducts to order based on what's included in your API request. | Website URL in payload? | Website product specified? | Subproducts specified? | What gets ordered | | ----------------------- | -------------------------- | ---------------------- | -------------------------- | | ✅ Yes | ❌ No | N/A | All enabled subproducts | | ✅ Yes | ✅ Yes | ✅ Yes | Only specified subproducts | | ✅ Yes | ✅ Yes | ❌ No | All enabled subproducts | | ❌ No | ✅ Yes | ✅ Yes | Only specified subproducts | | ❌ No | ✅ Yes | ❌ No | All enabled subproducts | * If you don't submit a `website_url`, the business name and address are required so Middesk can discover the business's website to perform further analysis. * If you submit a `website_url`, the business name and address are optional for website orders. > **Note** > > If you combine a website order with other order types (such as `business_verification_verify`), the name and address may still be required by those other orders. #### Review the analysis results Once your order completes, see the results in the [GET /business](/api-reference/business-verification/businesses/retrieve-a-business) payload or the `business.updated` [webhook](../build/webhooks), depending on your integration. For a high-level summary of the outcome, review these review tasks: | Summary | Key | | ----------------------------------------------------------------- | -------------------------------- | | Is the website purchased but has no content? | `website_parked` | | Is the website online? | `website_status` | | Is the website URL submitted or discovered? | `website_url_discovered` | | Does the website contain a match to the submitted office address? | `web_address_verification` | | Does the website contain a match to the submitted business name? | `web_business_name_verification` | | Does the website contain a match to the submitted person? | `web_person_verification` | | Does the website contain a match to the submitted phone number? | `web_phone_number_verification` | | Does the website contain a match to the submitted email address? | `web_email_address_verification` | | What is the web presence quality rating? | `web_presence_quality` | | Does the submitted website URL belong to the business? | `website_url_domain_ownership` | | Does the web presence include any risky keyword hits? | `risky_keywords` | To see the results in more detail, look at the [Website object](/reference/website) in the payload as well as the specific [Web Analysis review tasks](/online-presence/web-presence/review-tasks). Middesk also returns any third-party profiles associated with the business as [Profile objects](/reference/profile) under the top-level `profiles` key. This includes platforms such as Google, Facebook, LinkedIn, Instagram, Yelp, BBB, Trustpilot, X, and TikTok. Check the business's review tasks by requesting the full business payload using the [GET /businesses endpoint](/api-reference/business-verification/businesses/retrieve-a-business). For example, use the Website Status review task to evaluate whether the website is online. **`Ruby`** ```ruby title="Ruby" require 'net/http' require 'net/https' require 'json' def send_request business_id = "" uri = URI("https://api.middesk.com/v1/businesses/#{business_id}") # Create client http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER # Create Request req = Net::HTTP::Get.new(uri) # Add headers req.add_field "Accept", "application/json" # Add headers req.add_field "Authorization", "Basic " # Fetch Request res = http.request(req) response = JSON.parse(res.body) website_status_task = response['review']['tasks'].find { |task| task['key'] == 'website_status' } if website_status_task['status'] == 'success' puts 'Website online' else puts 'Website offline' end rescue StandardError => e puts "HTTP Request failed (#{e.message})" end ``` **`Python`** ```python title="Python" import requests from requests.auth import HTTPBasicAuth def send_request(): business_id = "" url = f"https://api.middesk.com/v1/businesses/{business_id}" headers = { "Accept": "application/json", "Authorization": "Basic " } try: # Make the request response = requests.get(url, headers=headers, auth=HTTPBasicAuth('', '')) # Parse the response JSON response_data = response.json() website_status_task = next((task for task in response_data['review']['tasks'] if task['key'] == 'website_status'), None) if website_status_task and website_status_task['status'] == 'success': print('Website online') else: print('Website offline') except requests.exceptions.RequestException as e: print(f"HTTP Request failed ({e})") send_request() ``` **`JavaScript`** ```javascript title="JavaScript" const businessId = ""; const url = `https://api.middesk.com/v1/businesses/${businessId}`; const headers = { "Accept": "application/json", "Authorization": "Basic " }; try { // Make the request using fetch const response = await fetch(url, { headers }); // Check if the request was successful if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseData = await response.json(); const websiteStatusTask = responseData.review.tasks.find(task => task.key === 'website_status'); if (websiteStatusTask && websiteStatusTask.status === 'success') { console.log('Website online'); } else { console.log('Website offline'); } } catch (error) { console.error(`HTTP Request failed: ${error.message}`); } } sendRequest(); ``` #### Inspect individual quality indicators Use `web_presence_quality` to determine an overall quality rating of `High`, `Moderate`, `Low`, or `Not Available` for the business's web presence. You can also inspect each quality indicator individually and derive an outcome based on your own heuristics. For example, a newly formed business may have a recently registered domain and limited content diversity. In that case, you may want to ignore those ratings when determining your outcome. The following table lists the quality indicators and their keys within the `website` object. Each indicator includes a rating field that returns a `positive`, `neutral`, or `negative` value. If an indicator cannot be determined, it is absent from the payload. | Quality Indicator | Description | Key | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------- | | Broken links | An evaluation of links found on the website leading to errors or nonexistent pages | `broken_links` | | Compliance info | An evaluation of compliance-related information, such as terms of service and privacy policy, that can be found on the business's website | `compliance_info` | | Contact info | An evaluation of contact information found within the content. Use the other review tasks associated with the website order to determine matches with submitted contact information. | `contact_info` | | Content diversity | An evaluation of the variation and type of information the website presents | `content_diversity` | | Domain age | An evaluation of how long the domain has been registered | `domain_age` | | Domain consistency | An evaluation of whether the domain matches the business name and branding | `domain_consistency` | | Domain ownership | An evaluation of how likely it is the domain belongs to the business | `domain_ownership` | | Filler text | An evaluation of content for any placeholder or filler text, like Lorem Ipsum | `filler_text` | | Https | An evaluation of HTTPS/TLS support | `https` | | Image quality | An evaluation of images to identify blurry or stock images | `image_quality` | | Last updated | An evaluation of how long ago the website was last modified | `last_updated` | | Page count | An evaluation of the total number of internal pages found on the website | `page_count` | | Spelling and grammar | An evaluation of spelling and grammatical mistakes and inconsistencies | `spelling_and_grammar` | | Testimonials | An evaluation of customer testimonials or reviews found on the website | `testimonials` | | Third party profile links | An evaluation of links to third-party profiles (social media, review sites, and so on) found on the website | `third_party_profile_links` | | Top Level Domain | An evaluation of the [TLD](https://en.wikipedia.org/wiki/Top-level_domain) with respect to the website's quality | `top_level_domain` | | Update frequency | An evaluation of how often the website's content is updated | `update_frequency` | | US Business Presence | An evaluation of website signals that suggest the business operates within the United States | `us_business_presence` | Retrieve these additional website details with the `GET /businesses/{id}/website` endpoint. The following example iterates through and prints the quality indicator ratings: **`Ruby`** ```ruby title="Ruby" require 'net/http' require 'uri' require 'json' require 'base64' def print_indicators_quality_ratings # Replace with your actual business ID and API key business_id = "51c4b91e-f324-467b-86b5-9e0155bcc251" # Example business ID api_key = "YOUR_API_KEY_HERE" # Replace with your actual API key uri = URI.parse("https://api.middesk.com/v1/businesses/#{business_id}/website") # Create the HTTP Basic Auth header auth = Base64.strict_encode64("#{api_key}:") headers = { "Accept" => "application/json", "Authorization" => "Basic #{auth}" } # Create the HTTP request http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri.request_uri, headers) begin # Make the request response = http.request(request) # Raise an error if the response is not successful unless response.is_a?(Net::HTTPSuccess) puts "HTTP Request failed (#{response.code} #{response.message})" return end # Parse the JSON response data = JSON.parse(response.body) # Navigate to the indicators indicators = data.dig('rating', 'indicators') || [] if indicators.empty? puts "No indicators found in the response." return end # Print each indicator's name and rating puts "Indicators' Quality Ratings:" puts "----------------------------" indicators.each do |indicator| name = indicator['name'] || 'Unknown Indicator' rating = indicator['rating'] || 'No Rating' description = indicator['description'] || '' puts "#{name}: #{rating} (#{description})" end rescue JSON::ParserError puts "Error parsing JSON response." rescue StandardError => e puts "An error occurred: #{e.message}" end end print_indicators_quality_ratings # Sample Output: # Indicators' Quality Ratings: # ---------------------------- # Domain age: positive (3 to 10 years old) # Domain ownership: positive (High confidence) # Compliance info: positive (Found) # Spelling and grammar: positive (Good) # Contact info: positive (Found) # Content diversity: positive (High) # Https: positive (Enabled) # Broken links: negative (Some broken) # Filler text: positive (Minimal) # Page count: positive (High) # Image quality: positive (Good) ``` **`Python`** ```python title="Python" import requests from requests.auth import HTTPBasicAuth def print_indicators_quality_ratings(): # Replace with your actual business ID and API key business_id = "51c4b91e-f324-467b-86b5-9e0155bcc251" # Example business ID api_key = "YOUR_API_KEY_HERE" # Replace with your actual API key url = f"https://api.middesk.com/v1/businesses/{business_id}/website" headers = { "Accept": "application/json" } try: # Make the GET request with HTTP Basic Authentication response = requests.get(url, headers=headers, auth=HTTPBasicAuth(api_key, '')) # Raise an exception if the request was unsuccessful response.raise_for_status() # Parse the JSON response data = response.json() # Navigate to the indicators indicators = data.get('rating', {}).get('indicators', []) if not indicators: print("No indicators found in the response.") return # Print each indicator's name and rating print("Indicators' Quality Ratings:") print("----------------------------") for indicator in indicators: name = indicator.get('name', 'Unknown Indicator') rating = indicator.get('rating', 'No Rating') description = indicator.get('description', '') print(f"{name}: {rating} ({description})") except requests.exceptions.HTTPError as http_err: print(f"HTTP error occurred: {http_err}") # for example, 404 Not Found except requests.exceptions.RequestException as req_err: print(f"Request error occurred: {req_err}") # Other request-related errors except ValueError: print("Error parsing JSON response.") except KeyError as key_err: print(f"Missing expected data in response: {key_err}") if __name__ == "__main__": print_indicators_quality_ratings() ''' Sample output Indicators' Quality Ratings: ---------------------------- Domain age: positive (3 to 10 years old) Compliance info: positive (Found) Spelling and grammar: positive (Good) Contact info: positive (Found) Content diversity: positive (High) Https: positive (Enabled) Broken links: negative (Some broken) Filler text: positive (Minimal) Page count: positive (High) Image quality: positive (Good) ''' ``` **`JavaScript`** ```javascript title="JavaScript" const axios = require('axios'); async function printIndicatorsQualityRatings() { // Replace with your actual business ID and API key const businessId = "51c4b91e-f324-467b-86b5-9e0155bcc251"; // Example business ID const apiKey = "YOUR_API_KEY_HERE"; // Replace with your actual API key const url = `https://api.middesk.com/v1/businesses/${businessId}/website`; try { const response = await axios.get(url, { headers: { 'Accept': 'application/json', 'Authorization': `Basic ${Buffer.from(`${apiKey}:`).toString('base64')}` } }); const data = response.data; // Navigate to the indicators const indicators = data.rating && data.rating.indicators ? data.rating.indicators : []; if (indicators.length === 0) { console.log("No indicators found in the response."); return; } // Print each indicator's name and rating console.log("Indicators' Quality Ratings:"); console.log("----------------------------"); indicators.forEach(indicator => { const name = indicator.name || 'Unknown Indicator'; const rating = indicator.rating || 'No Rating'; const description = indicator.description || ''; console.log(`${name}: ${rating} (${description})`); }); } catch (error) { if (error.response) { // Server responded with a status other than 2xx console.error(`HTTP error occurred: ${error.response.status} ${error.response.statusText}`); } else if (error.request) { // No response received console.error("No response received:", error.request); } else { // Other errors console.error("Error:", error.message); } } } printIndicatorsQualityRatings(); // Sample Output: // Indicators' Quality Ratings: // ---------------------------- // Domain age: positive (3 to 10 years old) // Compliance info: positive (Found) // Spelling and grammar: positive (Good) // Contact info: positive (Found) // Content diversity: positive (High) // Https: positive (Enabled) // Broken links: negative (Some broken) // Filler text: positive (Minimal) // Page count: positive (High) // Image quality: positive (Good) ``` ### Access more details The API also exposes a `source` object for each indicator to illustrate how the indicator quality rating was derived. This includes a human-readable `explanation` and, when relevant, `examples` from the retrieved dataset for the indicator. For example, the `image_quality` indicator returns a list of source URLs for any stock images detected, the `spelling_and_grammar` indicator lists citations for any found mistakes or inconsistencies, and the `broken_links` indicator returns a list of URLs found on the website that do not resolve. To access this expanded view, add the query parameter `include` with the value `indicator_details` to the business website endpoint. For example: `https://api.middesk.com/businesses/{id}/website?include=indicator_details` Here is an example of the expanded quality rating indicator with the `source` key: **`JSON`** ```json title="JSON" { "type": "image_quality", "name": "Image quality", "rating": "negative", "source": { "examples": [ { "link": "https://images.unsplash.com/photo-1637684666451-423047d6bf5e?ixid=M3wzOTE5Mjl8MHwxfHNlYXJjaHw4fHxzdGFydHVwfGVufDB8fHx8MTcxNDg3ODI0Nnww\u0026ixlib=rb-4.0.3\u0026auto=format\u0026fit=crop\u0026w=1920", "location": "https://example.com/contact", "classification": "stock_image" }, { "link": "https://images.unsplash.com/photo-1588856122867-363b0aa7f598?ixid=M3wzOTE5Mjl8MHwxfHNlYXJjaHw1fHxzdGFydHVwfGVufDB8fHx8MTcxNDg3ODI0Nnww\u0026ixlib=rb-4.0.3\u0026auto=format\u0026fit=crop\u0026w=328\u0026h=332", "location": "https://example.com/", "classification": "stock_image" }, { "link": "https://images.unsplash.com/photo-1519389950473-47ba0277781c?ixid=M3wzOTE5Mjl8MHwxfHNlYXJjaHwyfHxzdGFydHVwfGVufDB8fHx8MTcxNDg3ODI0Nnww\u0026ixlib=rb-4.0.3\u0026auto=format\u0026fit=crop\u0026w=1224\u0026h=400", "location": "https://example.com/", "classification": "stock_image" }, { "link": "https://images.unsplash.com/photo-1456406644174-8ddd4cd52a06?ixid=M3wzOTE5Mjl8MHwxfHNlYXJjaHw2fHxzdGFydHVwfGVufDB8fHx8MTcxNDg3ODI0Nnww\u0026ixlib=rb-4.0.3\u0026auto=format\u0026fit=crop\u0026w=606\u0026h=304", "location": "https://example.com/about", "classification": "stock_image" }, { "link": "https://images.unsplash.com/photo-1553729459-efe14ef6055d?auto=format\u0026fit=crop\u0026w=328\u0026h=264", "location": "https://example.com/company", "classification": "stock_image" } ], "explanation": "Many stock images were found." }, "value": "poor", "description": "Poor" } ``` > **Get a demo** > > Contact your account manager or [contact sales](https://www.middesk.com/contact-sales) to inquire about access. > Use the Middesk Web Analysis API to evaluate a business's web presence quality through automated analysis of their website's content, domain ownership, compliance information, and other indicators. ## Docs - [Web analysis review tasks](https://docs.middesk.com/online-presence/web-presence/review-tasks.md): Understand the web review tasks for Web Analysis that summarize verification checks performed on business websites and web profiles.