Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Recipes for Other Gallery Types: Event, Course List, Discussion Forum, Q&A, Dataset, Software App and Image Metadata
A type is chosen by what the page really is, not by an appearance in the gallery: an online-only event isn't eligible for Event, a product page's Q&A for QAPage, or book reviews for DiscussionForumPosting. We give Bookstore-based cards for Event, Discussion forum, Q&A and Image metadata, explain which types don't fit Bookstore and the carousel limit in Türkiye, and test the cards with a rule table in xUnit.
Store Information at the Organization Level: Logo, Contact Points, MerchantReturnPolicy, Shipping Policy and Precedence
Return and shipping policies aren't written into every product page; they are defined once under OnlineStore at the store level, product offers point to them with @id, and only exceptions are overridden at product level. For Bookstore we produce MerchantReturnPolicy and ShippingService from a single StorePolicy object and cover Türkiye's 14-day withdrawal right and Google's precedence between feeds, Search Console and markup.
Review Snippets and AggregateRating: Whose Reviews Count? The Self-Serving Review Rule, Rating Math and Risks
Only reviews that are visible on the page, come from users and belong to the reviewed item are eligible for star ratings; a store writing its own rating into Organization runs into the self-serving rule. We filter Bookstore's book reviews through moderation, get the average from one query that EF Core translates to SQL, round it once, and keep page and markup identical with tests.
Product Structured Data: Product Snippet or Merchant Listing? Product, Offer and Book for a Book Page
If the product can be bought on the page, merchant listing rules apply: an Offer is required and the price must be above zero; if not, it's a product snippet. On Bookstore's book page we co-type Product with Book, produce price and stock from the same object as the visible page, mark up the sale price and its end, and pin it all down with xUnit tests.
Measuring the Impact of an SEO Change: Before/After Analysis, Seasonality, Annotations and Honest Reporting
You measure the effect of an SEO change against a control group of similar unchanged pages, with whole-week windows and against the range of normal weekly variation; without a control group, season and holidays mix with the effect. We cover writing a hypothesis, annotations, outside factors, a C# analysis on synthetic data, the limits of split tests on a small site and an honest impact report.
The SEO Impact of Core Web Vitals: What Google Says, CrUX Field Data and Building Your Own RUM with web-vitals
According to Google, Core Web Vitals are used by the ranking systems but guarantee no ranking, and relevance comes first; the assessment uses field data from real users, not the Lighthouse score. We cover the thresholds and the 75th percentile, who CrUX includes, the URL groups of the Search Console report, the CrUX API in C# and an ASP.NET Core RUM endpoint that computes p75 the way Search Console does.
Privacy and Consent in Analytics: The KVKK Cookie Guide, Consent Mode and Cookieless Alternatives
You do not load the analytics tag before consent, and when the consent rate changes, GA4's number drops without any change in traffic; you tell them apart with a source consent does not affect. We cover what the KVKK cookie guide means for measurement, ITrackingConsentFeature in ASP.NET Core, consent-gated loading in Angular, basic vs advanced Consent Mode, the 2026 change and cookieless alternatives. Not legal advice.
Measuring On-Site Behavior with GA4: The Event Model, page_view in an Angular SPA, Custom Events and Key Events
In an Angular SPA you send page_view either through enhanced measurement's history tracking or by hand, never both; if you send it by hand, do it inside a TitleStrategy, because the router writes the title after NavigationEnd. We cover GA4's event model, key events, gtag with a CSP nonce in Razor pages, events that matter for a blog and Measurement Protocol code that sends no personal data.
The Search Console API and BigQuery Export: Automating Your Own SEO Report in C#
To keep Search Console data beyond 16 months, you pull each day separately from the Search Analytics API into your own database or turn on the BigQuery bulk export from today on; neither fills in past history. We cover service account access, paging, quotas, testing with a fake handler, an idempotent SQL Server archive, a threshold-based weekly report and the export's cost notes, with C# code.
The Search Console Performance Report in Depth: Position, CTR, Regex Filters, Branded Queries and Query Groups
In the Performance report, position is the average of the topmost result per query, and because the property and page views aggregate differently, CTR differs between the two tabs. We cover anonymized queries, the 1,000-row and 16-month limits, the Turkish character trap in RE2 regexes, the branded filter, query groups, annotations and C# code that finds low-CTR queries against the site's own CTR.
Measuring SEO: Which Question, Which Data? Why Search Console, GA4, Server Logs and CrUX Disagree
Search Console, GA4, server logs and CrUX count different parts of the same visit, so they give different numbers; the right number depends on the question you ask. We cover the question-metric-source mapping, why the numbers disagree, C# code that separates Google traffic in logs using Google's Referer rules, and the measurement options for mertozen.com.
Testing and Monitoring Structured Data: Rich Results Test, Schema Markup Validator, Search Console and Automated CI Checks
The Rich Results Test checks eligibility for Google's rich results and the Schema Markup Validator checks schema.org validity, but only tests that run on every build catch regressions. We cover URL Inspection and Search Console reports, JSON-LD tests with xUnit and WebApplicationFactory, Playwright checks for Angular SSR and post-deploy smoke tests, with real passing and failing output.