Technical SEO

Write a robots.txt file to block folders

Description: Write a robots.txt for all bots which blocks the folders /admin/ and /tmp/, but allows the file /admin/help.html. Add the sitemap https://example.com/sitemap.xml.

Hint:

  • Use Disallow for blocked folders, Allow for the exception and Sitemap with the full address.

Solution

User-agent: *
Disallow: /admin/
Disallow: /tmp/
Allow: /admin/help.html

Sitemap: https://example.com/sitemap.xml
Test result of the rules above

Googlebot /admin/users Blocked
Googlebot /admin/help.html Allowed
Googlebot /tmp/cache.txt Blocked
Googlebot /about/ Allowed

How it works

  • The longer rule Allow: /admin/help.html wins over the shorter Disallow: /admin/ for that file.
  • The test shows that only the intended paths are blocked.

Read Robots.txt.

Block all PDF files and URLs with a parameter in robots.txt

Description: Write a robots.txt rule to block all PDF files, and all URLs which contain ?sessionid=.

Hint:

  • * matches any text, and $ marks the end of the URL.

Solution

User-agent: *
Disallow: /*.pdf$
Disallow: /*?sessionid=
Test result of the rules above

Googlebot /docs/manual.pdf Blocked
Googlebot /docs/manual.pdf?download=1 Allowed
Googlebot /shop/?sessionid=abc123 Blocked
Googlebot /shop/ Allowed

How it works

  • /*.pdf$ matches any path that ends with .pdf. The URL with ?download=1 after it does not end with .pdf, so it is not matched by this rule.
  • /*?sessionid= matches any URL which has that parameter.

Read Robots.txt.

Add a canonical tag to a filtered page

Description: The page https://example.com/shoes/?sort=price&color=red shows the same shoes as https://example.com/shoes/ with a filter. Add a canonical tag so that search engines index the main page.

Hint:

  • Put the tag in the head and use the full URL of the main page.

Solution

<!-- On https://example.com/shoes/?sort=price&color=red -->
<head>
  <link rel="canonical" href="https://example.com/shoes/">
</head>

How it works

  • The canonical tag tells Google that the clean URL is the preferred version.
  • The main page itself should have a self referencing canonical with its own URL.

Read Canonical URLs.

Create an XML sitemap for three pages

Description: Create an XML sitemap for the pages https://example.com/, https://example.com/about/ and https://example.com/contact/.

Hint:

  • Use the urlset tag with the sitemap namespace, and one url with loc for each page.

Solution

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <lastmod>2026-09-01</lastmod>
  </url>
  <url>
    <loc>https://example.com/about/</loc>
    <lastmod>2026-08-12</lastmod>
  </url>
  <url>
    <loc>https://example.com/contact/</loc>
    <lastmod>2026-08-12</lastmod>
  </url>
</urlset>

How it works

  • The XML was checked and it is well formed (every tag is closed).
  • lastmod is optional, but add it only if it is the real date of the last change.
  • Save it as sitemap.xml in the root, add it to robots.txt and submit it in Search Console.

Read XML Sitemap.

Write Article structured data in JSON-LD

Description: Write JSON-LD for an article titled “How to Choose Running Shoes”, published on 2026-05-10, written by “Anita Rao”, on the site “Run Daily”.

Hint:

  • Use @type: Article, and a script tag of type application/ld+json.

Solution

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to Choose Running Shoes",
  "datePublished": "2026-05-10",
  "author": {
    "@type": "Person",
    "name": "Anita Rao"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Run Daily"
  }
}
</script>

How it works

  • The JSON was parsed by a tool, so the commas and quotes are right.
  • The markup must match the visible page: the same headline, the same author and the same date.
  • Test it with the Rich Results Test or the Schema Markup Validator.

Read Structured Data.

Write BreadcrumbList structured data

Description: Write breadcrumb markup for the page https://example.com/shoes/running-shoes/ with the path Home > Shoes > Running Shoes.

Hint:

  • Use itemListElement with a ListItem for each step and the position number.

Solution

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
    { "@type": "ListItem", "position": 2, "name": "Shoes", "item": "https://example.com/shoes/" },
    { "@type": "ListItem", "position": 3, "name": "Running Shoes" }
  ]
}
</script>

How it works

  • The positions start from 1. The last item is the current page, so the item URL is optional.
  • The markup should match the breadcrumb path which users see on the page.

Read Structured Data and Internal Linking.

Add hreflang tags for English and French pages

Description: The English page is https://example.com/guide/ and the French page is https://example.com/fr/guide/. Add the hreflang tags.

Hint:

  • Every version must list both versions, including itself.

Solution

<!-- In the head of BOTH pages -->
<link rel="alternate" hreflang="en" href="https://example.com/guide/">
<link rel="alternate" hreflang="fr" href="https://example.com/fr/guide/">
<link rel="alternate" hreflang="x-default" href="https://example.com/guide/">

How it works

  • The links are reciprocal, so Google can trust them.
  • x-default is for users whose language is not in the list.

Read International SEO and Hreflang.

Redirect old URLs to new URLs with .htaccess

Description: Redirect /old-page/ to https://example.com/new-page/ with a 301, and redirect all http traffic to https.

Hint:

  • Use Redirect 301 for one page, and RewriteRule with a condition for https.

Solution

Redirect 301 /old-page/ https://example.com/new-page/

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

How it works

  • The first line is a permanent redirect for one URL.
  • The rewrite rule runs when the request is not https and sends the same path to https.
  • After you save the file, check with curl -I that the status is 301 and that the Location line is correct. This file needs the Apache server with mod_rewrite enabled.

Read Redirection.