Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
SEO-Friendly URL Design: Slugs, Lowercase, Trailing Slashes and Query Parameters
An SEO-friendly URL is single and permanent: lowercase, readable words separated by hyphens, a consistent trailing slash and a query free of parameters that do not change the content. We look at a C# function that turns Turkish titles into ASCII slugs, 301 normalization in ASP.NET Core, the History API instead of fragments in the Angular router, and mertozen.com slugs, with real outputs.
A robots.txt Guide: RFC 9309, Allow/Disallow Rules and What Not to Block
robots.txt controls crawling, not indexing: a crawler follows the one group carrying its name, the longest matching rule wins, and a robots.txt returning 5xx stops crawling. We test RFC 9309 rules in C#, generate robots.txt per environment in ASP.NET Core, see Angular SSR giving robots.txt a one-year cache header, and read mertozen.com's file.
noindex and X-Robots-Tag: Correctly Keeping Pages and PDFs out of the Index
The way to keep a page or PDF out of the index is noindex, not robots.txt: a noindex on a blocked URL is never seen, and the Removals tool only hides a URL for about six months. We build an X-Robots-Tag middleware in ASP.NET Core and look at the static file ordering bug, the risk of noindex added with JavaScript in Angular, and server route headers, with real outputs.
XML Sitemaps and IndexNow: Generating Dynamic Sitemaps in ASP.NET Core and Announcing Changes
A sitemap is a hint to Google: changefreq and priority are ignored, lastmod is used only when verifiably accurate, and a file holds at most 50,000 URLs and 50 MB. We stream a sitemap from EF Core and measure it with 108,000 URLs, evict the output cache on publish, set up IndexNow for Bing and Yandex, and look at a build-time sitemap in Angular and mertozen.com's sitemap.
Canonical URLs: Managing Duplicate Content and the Canonical Google Chooses
rel=canonical is a signal, not a command: Google picks the URL on which redirects, canonicals, the sitemap and internal links agree. We write a canonical tag helper in ASP.NET Core that ignores the Host header and drops needless parameters, and look at the Link header for PDFs, a single canonical in Angular SSR and Google's December 2025 JavaScript rule, with real outputs.
HTTP Status Codes and Soft 404s: How Google Interprets 404, 410, 5xx and 429
Google treats 404 and 410 the same and removes the URL from the index; 5xx and 429 slow crawling, and URLs drop if errors persist. A not-found page returning 200 is a soft 404. We cover error pages that keep the status code in ASP.NET Core, 503 with Retry-After, the rate limiter, HEAD and 405, a real 404 with RESPONSE_INIT in Angular SSR, and mertozen.com's switch from 404 to 503 on CMS errors.
Redirects: 301, 302, 307, 308 and Doing Them Right in ASP.NET Core
Use 301 or 308 for permanent moves: Google treats them as a strong canonical signal and 302 and 307 as weak ones, while 308 and 307 keep POST. We look at ASP.NET Core's URL Rewriting Middleware, UseHttpsRedirection with its 307 default, single-hop 301s from a slug history in the database, chains, and redirectTo returning 302 in Angular SSR, with real outputs.
JavaScript SEO: CSR, SSR, SSG and How Googlebot Renders Pages
Content to be indexed must be in the first HTML: Googlebot runs JavaScript in a render queue, and many crawlers never run it. We measure the same Angular page as SSG, SSR and CSR with curl and headless Chrome, and see why Lighthouse gives the CSR page 100, why dynamic rendering is a workaround, and pitfalls such as content behind clicks.
SEO with Angular SSR: Server Routes, RenderMode, Meta Tags and Hydration
In Angular the render mode is chosen per route: a blog post uses Prerender with getPrerenderParams, search uses Server, the account page uses Client. We look at a service managing Title, Meta and canonical through DOCUMENT, REQUEST and RESPONSE_INIT, the HTTP transfer cache halving API calls, the isPlatformBrowser and useValue pitfalls, and allowedHosts rejecting even localhost with 400, with real outputs.
hreflang and Multilingual Sites: URL Strategy for TR/EN and x-default
Each language needs its own URL and its own canonical, linked reciprocally with hreflang; since Googlebot sends no Accept-Language, the other version of a page that switches language by cookie or header disappears for the crawler. We cover route-based language and an hreflang tag helper in ASP.NET Core, a canonical bug Lighthouse missed in Angular i18n, and mertozen.com's move from ?lang= to /en/.
Crawl Budget, Server Log Analysis and Verifying Googlebot
Crawl budget is a concern for sites with millions of pages or thousands changing daily; on a small site, first check whether the Googlebot in your logs is real. We produce W3C logs in ASP.NET Core in the same format as IIS, write a C# tool that extracts bot traffic, and verify Googlebot with reverse and forward DNS and Google's published IP range JSON files.
Site Migrations and Domain Changes: URL Mapping, 301 Plans and Change of Address
In a site migration every old URL goes to its final target in one 301 hop; redirects stay for at least a year, and Change of Address is used only for domain changes, for every www and non-www variant. We build a chain-checked redirect table from a CSV mapping and a script that verifies every old URL for 301, a 200 target and its canonical, and read mertozen.com's /en/ move against that checklist.