<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hwee-Boon Yar]]></title><description><![CDATA[Hwee-Boon Yar]]></description><link>https://hboon.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 12 Nov 2026 10:10:10 GMT</lastBuildDate><atom:link href="https://hboon.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to check a new page for noindex, canonical and link rel mistakes after deploy]]></title><description><![CDATA[A few curl and grep commands, plus a short prompt for your coding agent, that catch a leaked noindex, a wrong canonical, a robots.txt Disallow or a paid…]]></description><link>https://hboon.hashnode.dev/check-new-page-noindex-canonical-link-rel</link><guid isPermaLink="true">https://hboon.hashnode.dev/check-new-page-noindex-canonical-link-rel</guid><category><![CDATA[SEO]]></category><category><![CDATA[AI]]></category><category><![CDATA[webdev]]></category><category><![CDATA[devtools]]></category><category><![CDATA[Bash]]></category><dc:creator><![CDATA[Hwee-Boon Yar]]></dc:creator><pubDate>Mon, 09 Nov 2026 03:25:15 GMT</pubDate><content:encoded><![CDATA[<p>I ship most new pages with a coding agent now. Landing pages, docs, blog posts. The agent writes the page, the build passes, the deploy goes out, and I look at the page in a browser. It looks fine.</p>
<p>The browser doesn't show the parts that decide whether a search engine may index the page. A <code>noindex</code> from a staging config can leak into production. Canonicals copied from a template can point at another page. Someone adds a <code>Disallow</code> to robots.txt and it covers a whole folder. Affiliate links go out without <code>rel="sponsored"</code>. None of these change how the page looks.</p>
<p>So after every deploy that adds or changes a public page, I run a few commands against the live URL. Total time is under a minute.</p>
<h2>What these commands can and can't tell you</h2>
<p>The commands read what your server sends: status codes, redirects, headers, HTML and robots.txt. They don't tell you whether Google indexed the page. Google makes that call later, and it treats a canonical as a strong signal it weighs against other signals.</p>
<p>For actual index status, use <a href="https://support.google.com/webmasters/answer/9012289">URL Inspection in Search Console</a>. It also shows the HTML Googlebot received, which helps when your server sends different content to bots.</p>
<p>What the commands do catch: the mistakes you made yourself, on the page you just shipped.</p>
<h2>Status and redirects</h2>
<p>Start with the response code and where the URL ends up:</p>
<pre><code class="language-bash">curl -sIL -o /dev/null -w '%{http_code} %{url_effective} (%{num_redirects} redirects)\n' http://getlinkbunny.com/
</code></pre>
<pre><code>200 https://getlinkbunny.com/ (1 redirects)
</code></pre>
<p>You want a <code>200</code> on the URL you intend to publish. If the final URL differs from the one in your sitemap or internal links, fix the links. If the page returns a <code>404</code> or redirects to the homepage, the route didn't deploy the way you think.</p>
<h2>X-Robots-Tag header</h2>
<p>A <code>noindex</code> can come from an HTTP header instead of the HTML. Hosting configs, CDN rules and preview environments can add it. Check the headers on every hop:</p>
<pre><code class="language-bash">curl -sIL https://example.com/new-page | grep -iE '^(x-robots-tag|link):'
</code></pre>
<p>No output means neither header was sent. If you see <code>x-robots-tag: noindex</code> on a production URL, find the config that adds it. Google's <a href="https://developers.google.com/search/docs/crawling-indexing/block-indexing">block indexing docs</a> say the meta tag and the header have the same effect, so one is enough to keep the page out. The <code>link:</code> match also catches a canonical sent as a header, which some sites use for PDFs and other non-HTML files.</p>
<h2>Meta robots tag</h2>
<p>Next, the robots meta tag in the HTML:</p>
<pre><code class="language-bash">curl -sL https://getlinkbunny.com/ | grep -ioE '&lt;meta[^&gt;]+name="(robots|googlebot)"[^&gt;]*&gt;'
</code></pre>
<pre><code>&lt;meta name="robots" content="index, follow"&gt;
</code></pre>
<p>Look for <code>noindex</code> or <code>none</code> in <code>content</code>. Missing tag is fine; indexing is the default. The grep assumes double quotes around the attribute value. If your framework writes single quotes, adjust the pattern.</p>
<p>Keep in mind that curl doesn't run JavaScript. If your app injects the meta tag on the client, you won't see it here. For prerendered or server-rendered pages, the curl output is what a crawler reads first.</p>
<h2>Canonical URL</h2>
<pre><code class="language-bash">curl -sL https://getlinkbunny.com/ | grep -ioE '&lt;link[^&gt;]+rel="canonical"[^&gt;]*&gt;'
</code></pre>
<pre><code>&lt;link rel="canonical" href="https://getlinkbunny.com/"&gt;
</code></pre>
<p>Check three things: the canonical points at this page and not at the homepage or a sibling page, it uses the production host and not a staging or preview domain, and it's an absolute URL. Google's <a href="https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls">duplicate URL docs</a> recommend absolute URLs for this reason. When an agent creates a page by copying an existing one, check this first, since it can keep the old head tags.</p>
<h2>robots.txt</h2>
<pre><code class="language-bash">curl -s https://getlinkbunny.com/robots.txt | grep -iE '^(user-agent|disallow|allow):'
</code></pre>
<pre><code>User-agent: *
Allow: /
</code></pre>
<p>Compare each <code>Disallow</code> line with the path of your new page. A <code>Disallow</code> rule for <code>/docs</code> also blocks <code>/docs/new-guide</code>.</p>
<p>Check robots.txt before you trust a <code>noindex</code>. If robots.txt blocks a URL, Google never fetches the page, so it never sees a <code>noindex</code> on it. The block indexing docs say such a page can still show up in results when other sites link to it. Don't use robots.txt to remove a page from search. Use <code>noindex</code> and leave the page crawlable.</p>
<h2>Outgoing link rel values</h2>
<p>Last, the links. Google's <a href="https://developers.google.com/search/docs/crawling-indexing/qualify-outbound-links">outbound link docs</a> ask for <code>rel="sponsored"</code> on paid and affiliate links, <code>rel="ugc"</code> on user-submitted links like comments, and <code>rel="nofollow"</code> when neither fits and you don't want to vouch for the link. You can combine them, e.g. <code>rel="ugc nofollow"</code>.</p>
<p>This lists outgoing links that carry none of the three:</p>
<pre><code class="language-bash">url=https://example.com/new-page
origin=https://example.com
curl -sL "$url" \
  | grep -oiE '&lt;a [^&gt;]*href="https?://[^"]*"[^&gt;]*&gt;' \
  | grep -viE "href=\"$origin" \
  | grep -viE 'rel="[^"]*(nofollow|sponsored|ugc)'
</code></pre>
<p>Most links in the output are normal editorial links and should stay that way. Read the list for anything paid. To pull out likely affiliate links that lack <code>sponsored</code>, filter on your affiliate URL patterns:</p>
<pre><code class="language-bash">curl -sL "$url" \
  | grep -oiE '&lt;a [^&gt;]*href="https?://[^"]*"[^&gt;]*&gt;' \
  | grep -iE 'amzn\.to|[?&amp;](tag|ref|aff|affiliate)=|/go/' \
  | grep -viE 'rel="[^"]*sponsored'
</code></pre>
<p>The pattern list is a guess. Replace it with the patterns your affiliate programs use. The grep also misses links built with JavaScript, and links whose <code>rel</code> uses single quotes.</p>
<h2>One script for all of it</h2>
<p>I keep the checks in one file and pass the URL:</p>
<pre><code class="language-bash">#!/usr/bin/env bash
# usage: ./check-page.sh https://example.com/some/page
page_url="$1"
origin=$(echo "$page_url" | grep -oE '^https?://[^/]+')

echo "== Status and final URL"
curl -sIL -o /dev/null -w '%{http_code} %{url_effective} (%{num_redirects} redirects)\n' "$page_url"

echo "== X-Robots-Tag and Link headers"
curl -sIL "$page_url" | grep -iE '^(x-robots-tag|link):'

page_html=$(curl -sL "$page_url")

echo "== Meta robots"
echo "$page_html" | grep -ioE '&lt;meta[^&gt;]+name="(robots|googlebot)"[^&gt;]*&gt;'

echo "== Canonical"
echo "$page_html" | grep -ioE '&lt;link[^&gt;]+rel="canonical"[^&gt;]*&gt;'

echo "== robots.txt rules"
curl -s "$origin/robots.txt" | grep -iE '^(user-agent|disallow|allow):'

echo "== Outgoing links without nofollow, sponsored or ugc"
echo "$page_html" | grep -oiE '&lt;a [^&gt;]*href="https?://[^"]*"[^&gt;]*&gt;' \
  | grep -viE "href=\"$origin" \
  | grep -viE 'rel="[^"]*(nofollow|sponsored|ugc)'
</code></pre>
<p>An empty section means nothing matched. That's the result you want for headers, and fine for meta robots.</p>
<h2>A prompt for your coding agent</h2>
<p>The agent shipped the page, so the agent can check it too. I add this to the end of a page task, or keep it in my agent instructions file:</p>
<pre><code class="language-text">After deploying, run ./check-page.sh &lt;the new page's production URL&gt; and report:
- status code and final URL
- any noindex or none in X-Robots-Tag or meta robots
- the canonical URL, and whether it matches the page URL on the production host
- any robots.txt Disallow rule that covers the page path
- outgoing links that look paid or affiliate but have no rel="sponsored"
Fix anything that comes from our code or config. Do not change rel values on editorial links. Do not claim the page is indexed; these checks only read what the server sends.
</code></pre>
<p>The last line keeps the agent from reporting "page indexed" when it only saw a <code>200</code>.</p>
<h2>Free checkers that do the same reads</h2>
<p>If you'd rather paste a URL than run a script, I built two free checkers that need no signup. The <a href="https://getlinkbunny.com/tools/indexability-checker">indexability checker</a> reads the HTTP response, redirects, meta robots, X-Robots-Tag, canonical declarations and robots.txt availability for one page. The <a href="https://getlinkbunny.com/tools/nofollow-link-checker">nofollow link checker</a> lists the rel value of every link on one page, plus page-level nofollow from meta robots and X-Robots-Tag. Both read server HTML only and don't run JavaScript, same as curl, and neither reports Google index status.</p>
<p>I also build <a href="https://getlinkbunny.com">LinkBunny</a>, where coding agents handle nofollow link exchanges between sites.</p>
]]></content:encoded></item></channel></rss>