# On-page checks

> Triggers and fixes for titles, meta descriptions, headings, thin content, alt text, Open Graph, structured data and mixed content.

Source: https://seofix.ai/help/checks-on-page · Category: Issue reference · Updated: 2026-10-08

On-page checks read the HTML of each page SEOFix crawls. They run only on URLs that answer `200` with a `text/html` content type and are not blocked by a firewall. Every code on this page is recheckable: after you deploy a fix, [Verify fix](https://seofix.ai/help/verify-fix.md) confirms it in seconds.

Lengths are counted in characters of the text as found in the HTML. Most of these issues come from a shared layout or page template, so fix them there once. See [Fixing by template](https://seofix.ai/help/fixing-by-template.md).

## Titles

### TITLE_MISSING — Missing title tag

- **Severity**: error. **Recheckable**: yes.
- **Trigger**: the page has no `<title>` element, or its text is empty after trimming whitespace.
- **Why it matters**: the title is the main headline in search results and a strong ranking signal. Without one, search engines make one up.
- **How to fix**: add one unique, descriptive `<title>` of 30–60 characters inside `<head>`, usually generated from the page's main subject.

```html
<head>
  <title>Senior Accountant Jobs in Dubai | Example Jobs</title>
</head>
```

### TITLE_TOO_LONG — Title too long

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: the first `<title>` is longer than 60 characters (after trimming).
- **Details**: `length`.
- **Why it matters**: search engines cut titles at roughly 60 characters, hiding the end of the headline.
- **How to fix**: shorten the title to 60 characters or fewer. Put the distinctive words first. In templates, drop long suffixes (a full brand slogan) or cap the dynamic part.

### TITLE_TOO_SHORT — Title too short

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: the title is shorter than 15 characters (and not missing).
- **Details**: `length`.
- **Why it matters**: a very short title wastes the most visible ranking signal on the page.
- **How to fix**: expand it to 30–60 characters that describe the page, for example by adding the category, location or brand.

### MULTIPLE_TITLE_TAGS — Multiple title tags

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: more than one `<title>` element inside `<head>`.
- **Details**: `count`.
- **Why it matters**: with several titles, search engines pick one unpredictably.
- **How to fix**: keep exactly one `<title>` in `<head>`. This often happens when a layout and a page template, or a framework head manager and an SEO plugin, both add one. Remove one source.

## Meta descriptions

### META_DESCRIPTION_MISSING — Missing meta description

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: no `<meta name="description">` tag, or its `content` is empty.
- **Why it matters**: without one, search engines pick a snippet from the page, which usually lowers click-through.
- **How to fix**: add a `<meta name="description">` of 50–155 characters that summarises the page.

```html
<meta name="description" content="Browse 240 senior accountant jobs in Dubai. Filter by salary, company and visa sponsorship. Updated daily.">
```

### META_DESCRIPTION_TOO_LONG — Meta description too long

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: the first meta description's `content` is longer than 155 characters.
- **Details**: `length`.
- **Why it matters**: longer descriptions are truncated in search results.
- **How to fix**: shorten it to 155 characters or fewer, with the key information first.

### META_DESCRIPTION_TOO_SHORT — Meta description too short

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: the meta description is shorter than 50 characters (and not missing).
- **Details**: `length`.
- **Why it matters**: a very short description gives searchers little reason to click.
- **How to fix**: expand it to 50–155 characters.

### MULTIPLE_META_DESCRIPTIONS — Multiple meta descriptions

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: more than one `<meta name="description">` inside `<head>`.
- **Details**: `count`.
- **Why it matters**: search engines may ignore them or use the wrong one.
- **How to fix**: keep exactly one `<meta name="description">` in `<head>`. Find the second source (layout, plugin, head manager) and remove it.

## Headings and content

### H1_MISSING — Missing H1 heading

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: the page has no `<h1>` element.
- **Why it matters**: the H1 tells users and search engines what the page is about.
- **How to fix**: add exactly one `<h1>` with the page's main topic. If the visual heading is a styled `<div>` or `<span>`, change it to an `<h1>`.

### MULTIPLE_H1 — Multiple H1 headings

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: more than one `<h1>` element anywhere in the page (hidden ones included).
- **Details**: `count`.
- **Why it matters**: several H1s dilute the page's main topic.
- **How to fix**: keep a single `<h1>` and demote the others to `<h2>` or `<h3>`. Logos and site names in headers are a common second H1.

### THIN_CONTENT — Thin content

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: the visible text of `<body>` has fewer than 100 words, and the page is indexable (no `noindex`, and no canonical pointing to another URL). Text inside `<script>` and `<style>` is not counted; words are split on whitespace.
- **Details**: `word_count`.
- **Why it matters**: pages with very little text rarely rank and can drag down how search engines see the whole site.
- **How to fix**: add substantive content (aim for 300+ words), or merge the page into a stronger one and redirect or canonicalise it. If the page should not rank, add `noindex` (noindex and canonicalised pages are not flagged). If the text exists but only appears after JavaScript runs, render it server-side.

### IMAGES_MISSING_ALT — Images missing alt text

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: at least one `<img>` has no `alt` attribute at all. `alt=""` counts as present: it is the correct marking for decorative images.
- **Details**: `missing`, `total` (images on the page).
- **Why it matters**: alt text makes images accessible and lets search engines understand them.
- **How to fix**: give every `<img>` an `alt` attribute: descriptive text for meaningful images, `alt=""` for decorative ones. In templates, generate it from the content (product name, author name).

```html
<img src="/logos/emaar.png" alt="Emaar Properties logo">
<img src="/img/divider.svg" alt="">
```

## Open Graph

Open Graph tags control how links to your pages look when shared in social networks and chat apps.

### OG_TAGS_MISSING — Missing Open Graph tags

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: no `<meta property="og:title">` tag.
- **Why it matters**: shared links render without a proper title, text and image.
- **How to fix**: add `og:title`, `og:description`, `og:image` and `og:url`.

```html
<meta property="og:title" content="Senior Accountant Jobs in Dubai">
<meta property="og:description" content="240 open roles, updated daily.">
<meta property="og:image" content="https://example.com/og/jobs-dubai.png">
<meta property="og:url" content="https://example.com/jobs/accountant-dubai">
```

### OG_TAGS_INCOMPLETE — Open Graph tags incomplete

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: `og:title` exists, but at least one of `og:title`, `og:description`, `og:image`, `og:url` is missing or has empty `content`.
- **Details**: `missing` (the missing properties).
- **Why it matters**: without all four, shared links render without an image or with guessed text.
- **How to fix**: add the properties listed in `missing`.

### OG_URL_MISMATCH — og:url doesn't match canonical

- **Severity**: notice. **Recheckable**: yes.
- **Trigger**: the page has an `og:url`, and after normalising it (resolved to an absolute URL, host lowercased, default port and fragment removed) it differs from the page's canonical URL, or from the page's own URL when there is no canonical. Scheme, `www` and trailing slash all count as differences.
- **Details**: `og_url`, `expected`.
- **Why it matters**: shares are attributed to `og:url`; a different URL splits share counts and can show the wrong page.
- **How to fix**: set `og:url` to the same URL as `<link rel="canonical">`. In templates, build both from the same value.

## Structured data

### STRUCTURED_DATA_INVALID — Invalid structured data

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: a `<script type="application/ld+json">` block has one of these problems. One issue per problem type per page:

| `reason` | Meaning |
| --- | --- |
| `parse_error` | The block is not valid JSON. |
| `missing_context` | A top-level object has no `@context`. |
| `missing_type` | A top-level item is not an object, or an object (or an item in its `@graph`) has no `@type`. |

- **Details**: `reason`, `count` (blocks with that problem).
- **Why it matters**: JSON-LD that does not parse or lacks `@context` or `@type` is ignored, so the page loses rich results.
- **How to fix**: emit valid JSON (no trailing commas, no unescaped quotes or line breaks inside strings, no template placeholders left in), with `"@context": "https://schema.org"` and an `@type` on every node. Serialise it with your language's JSON encoder rather than string concatenation.

```html
<script type="application/ld+json">
{"@context": "https://schema.org", "@type": "JobPosting", "title": "Senior Accountant", "datePosted": "2026-10-01"}
</script>
```

## Security

These run only on `https://` pages.

### HTTP_LINK_ON_HTTPS — Insecure (HTTP) link on HTTPS page

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: an `https://` page has `<a href>` links to `http://` URLs on your own host (with or without `www`).
- **Details**: `targets` (up to 10 of the URLs).
- **Why it matters**: each such link costs a redirect and can trigger insecure-content warnings.
- **How to fix**: change internal links to `https://`, or use relative or root-relative URLs (`/jobs/...`). Check hard-coded links in content, menus and the CMS's site URL setting.

### MIXED_CONTENT — Mixed content

- **Severity**: warning. **Recheckable**: yes.
- **Trigger**: an `https://` page loads a subresource over `http://`: an `<img src>`, `<script src>`, `<iframe src>` or `<link rel="stylesheet" href>` starting with `http://`, on any host.
- **Details**: `count`, `samples` (up to 5 URLs).
- **Why it matters**: browsers block or flag insecure subresources, which can break the page and mark it not secure.
- **How to fix**: load every subresource over `https://`, or use relative URLs for your own assets. If a third-party host has no HTTPS, replace it.

```html
<!-- before -->
<img src="http://cdn.example.com/hero.jpg" alt="Dubai skyline">
<!-- after -->
<img src="https://cdn.example.com/hero.jpg" alt="Dubai skyline">
```

## Related

- [Issue reference](https://seofix.ai/help/issue-reference.md)
- [Indexability checks](https://seofix.ai/help/checks-indexability.md)
- [Fixing by template](https://seofix.ai/help/fixing-by-template.md)
- [Verify a fix](https://seofix.ai/help/verify-fix.md)
