External SEO Reports: Remediation

astrarad.com. Reports run 2026-08-09: Seobility (87 percent on page), Yoast, SEOptimer, PageSpeed Insights (mobile 86 / desktop 98), GTmetrix (93 / 99), Majestic. Backlinks excluded by request; the founder handles those separately.

What it is

Every finding from six external SEO tools, mapped to what is actually true in the codebase, then either fixed, verified as a false positive, marked founder-blocked, or declined with a reason. All fixes are built, gate-checked, verified in a real browser, and shipped to production on 2026-08-09 in 858fc2c, with the nav-link contrast follow-up in f5b7c39. [Corrected 2026-08-14] This paragraph originally read "the work is staged and waiting for a founder commit, nothing is deployed yet." That was already false when it was written: this file is inside 858fc2c's own diffstat, and wiki/log.md, added by that same commit, records "Committed and deployed the same evening."

Scenario: An imaging center director googles "teleradiology company" late on a Friday, lands on astrarad.com from her phone on hospital wifi, and the page paints before her attention moves on because the analytics script no longer competes with the hero image for the first connection. She taps "Plan your backlog clearance", the contact page opens with backlog-specific copy and a hidden intent field, and that URL carries no tracking-looking query string. [Corrected 2026-08-14] Originally "the contact form opens already set to backlog." The eight-option select it referred to was deleted on 2026-08-11 in e8f08d6; the fragment now drives page copy rather than a form control. See the addendum.

Fixed in this pass (7 items, all verified in the built output)

Report findingWhat was actually wrongFix and verification
FIXED H1 words not found in text (Seobility, the only on-page error) Of the whole H1, exactly two words never appeared in body prose: "inside" and "matters". Everything else already did. One sentence appended to the hero subheadline: "When it matters, a STAT read is back inside the hour." Restates the published STAT tier, adds no new claim. Verified: both words now appear twice in the built homepage.
FIXED Internal links with dynamic parameters (Seobility) Two homepage CTAs linked /contact?ask=rate-card and /contact?ask=backlog. Both now use URL fragments (/contact#rate-card, /contact#backlog): a fragment never mints a new crawlable URL. The contact page reads the fragment and still honours the legacy ?ask= form used across the corpus; query wins when both are present. Browser-verified: fragment prefills the form select, query param still works. [2026-08-14: still true, but no longer the whole picture] The fragment now sets the page's h1, intro copy, submit-button label and a hidden intent field, because the select was deleted on 2026-08-11; and two new query-parameter CTAs have since reopened the Seobility finding on the homepage. Both are detailed in the addendum.
FIXED No external links on the page (Seobility, Yoast, SEOptimer) Zero outbound links on the homepage; answer engines read that as a page that cites nothing. The HIPAA and BAA pillar now links "business associate" to the HHS guidance page (hhs.gov). Authoritative, on message, and phrased inside the existing sentence, which already uses the gate-safe "operates as a business associate under a signed BAA" wording.
FIXED No Apple touch icon (Seobility) Only an SVG favicon and a favicon.ico existed. 180x180 apple-touch-icon.png generated from the favicon mark on a solid dark square (iOS shows black behind transparent corners), linked in the head, present in dist.
FIXED Inefficient cache lifetimes, about 4 KB (PSI, GTmetrix) The root icons were the only uncached assets on the site: favicon.svg shipped max-age=0. Fonts, JS, CSS and /assets were already immutable or 7 day cached. 7 day Cache-Control headers added in netlify.toml for /favicon.svg, /favicon.ico and /apple-touch-icon.png.
FIXED Reduce unused JavaScript, 129 to 146 KB; third parties 166 KB (PSI, GTmetrix) gtag.js loaded eagerly in the head, competing with the LCP image and fonts for the first connection on slow links. The Angular side was already lazy-split in the August remediation. GA now loads after the window load event. The inline stub still queues page_view immediately, so analytics loses nothing; the 166 KB just leaves the critical path. This is the change most likely to move the mobile score of 86.
FIXED Insufficient color contrast, desktop only (PSI accessibility 96) Two genuine failures, both desktop-only. The green "SIGNED" label on the white sample report card measured 3.69 to 1 at 9px, and the top navigation links measured 4.05 to 1 on the dark header bar (floor is 4.5); mobile scores 100 because the card and the nav links do not render there. A custom scanner found the first; a post-deploy Lighthouse desktop run caught the second. SIGNED green darkened oklch 0.60 to 0.52, re-measured 5.1 to 1. Nav links given an explicit oklch 0.70 gray (narrowest selector; the global text-secondary token is correct everywhere else), about 5.0 to 1. Lighthouse desktop accessibility re-run after deploy: 100, color-contrast passing.

Verified non-issues (measured, no action taken)

Report findingWhy nothing was changed
N/A Avoid multiple page redirects (0.19 to 0.63s)The tools were fed http://astrarad.com. Measured live: http to https is a single 301 straight to the canonical URL, and www to apex likewise. There is no chain to collapse; one hop from an insecure entry URL is the floor.
N/A Non-composited animation, 1 elementThe infinite scan-sweep animation already runs on transform and opacity. The flagged element is the one-shot 700ms SVG stroke drawing effect on the ROI annotation; converting stroke-dashoffset to a composited property would break the effect for a rounding-error gain, and it honours prefers-reduced-motion already.
N/A Forced reflowThe scroll-reveal code only writes styles (class add plus transitionDelay); it performs no layout reads. The remaining trace entry is Angular hydration, not application code.
N/A Page response time 0.47s / TTFB 452msPrerendered HTML on the Netlify CDN with correct must-revalidate semantics; the deeper tool measured the server itself at 234ms. Not improvable from this repository.
N/A Duplicate anchor textsHeader and footer navigation intentionally repeat the same labels. Standard on nearly every site; changing footer labels to synonyms would cost clarity for zero ranking effect.
N/A Excessive DOM size, 645 elements645 is small. Lighthouse's warning threshold is 800 and its own severity was "low".
N/A Hreflang missingSingle-language, single-country site. Hreflang would be noise.
N/A Fonts, 167 KBAlready self-hosted, subset to three families, the two above-the-fold faces preloaded, immutable cached. This was done in the August remediation and re-verified today.

Founder-blocked as of 2026-08-09 (two have since cleared)

Report findingWhy blocked
OPEN TASK Business address on site and in schemaThe legal entity name and registered street address are founder question 2 on the standing list, unanswered. A placeholder address on a medical services site would be a real liability. The phone is published and detected by every tool, and still is. [Corrected 2026-08-14: no longer blocked] The founder answer landed 2026-08-13 in 37a9fda: Astrarad LLC, 8 The Green STE B, Dover, DE 19901, recorded in the Company fields drawer of DOCS/backlinks-guide.html. The site half of the finding still stands, since the live MedicalOrganization node still carries no PostalAddress, but this is now ordinary work rather than a founder dependency. It does need one deliberate decision first: whether a Delaware registered-agent address belongs on a fully remote medical services site. Note also the conflict recorded in wiki/features/listing-kit.md, that the entity was formed in 2020 against the site's "more than ten years."
PARTLY DONE Social profiles linked, sameAs in schemaNo LinkedIn or other company profile exists yet. The founder sequence is: regenerate the two broken logo files, create the LinkedIn page, then wire sameAs. Pointing sameAs at nothing is worse than leaving it empty. [Corrected 2026-08-14: this was false when written] The LinkedIn company page already existed. 858fc2c, the commit that created this file, also added a wiki log entry reading "the LinkedIn company page already exists ... Two documents in this repo asserted no company profile existed." Re-verified live today: linkedin.com/company/astrarad returns 200 as "AstraRad LLC", and DOCS/state/listing-progress.json records LinkedIn, Crunchbase and BBB as done. The logo files never gated it. What is genuinely missing is only the reverse link: the live Organization JSON-LD still emits no sameAs. That is a one-line engineering change with no founder dependency. Other profiles still do not exist and must not be pointed at.
BLOCKED Local Business schemaPartially a wrong recommendation: a national teleradiology group is not a local business, and MedicalOrganization (already emitted, with contactPoint, areaServed US, offer catalog) is the correct type. That structural half re-verifies live on 2026-08-14. The part that is real, a postal address on the org node, is blocked on the same founder answer as above. [Corrected 2026-08-14] That founder answer has since landed, so this row inherits the status of the address row above: an open task, not a blocker.

Declined, with reasons

Report findingReason
DECLINED Install a Facebook PixelAn ad-tech beacon on a healthcare-adjacent site that markets HIPAA alignment is a trust liability, there is no Facebook campaign to feed, and regulators have repeatedly fined health companies for exactly this. Declining is the professional answer.
DECLINED Remove inline stylesSome come from Angular [style.x] bindings, which cannot be hoisted out of the render pipeline; the rest are hand-written in component templates and could be moved to classes. Either way there is no ranking effect, so it is not worth the churn. [Corrected 2026-08-14] This originally read "Angular emits them as part of its render pipeline; removing them is not meaningfully possible." Only partly true: the repo carries 100 hand-written style="..." attributes in frontend/src/app against 71 [style.x] bindings. The DECLINED verdict is unchanged; only its reason was overstated.
DECLINED AMPGoogle retired AMP's ranking preference years ago.

Owned by the founder separately: backlinks

External factors scored 27 percent (Seobility) on 9 backlinks from 9 domains, 8 of 9 nofollow, as measured 2026-08-09. No re-measurement has been recorded since. Excluded from this pass by request. Two observations worth carrying into that work:

Deploy note. Everything above shipped on 2026-08-09 in 858fc2c, with the nav-link contrast follow-up in f5b7c39 eleven minutes later, and is live on astrarad.com. Re-verified live 2026-08-14. Gate-checked at build time (full npm run build green: 55 sitemap URLs, 352 JSON-LD references, 1,433 calendar links, 0 breaks). Desktop accessibility was re-audited live after deploy at 100, color-contrast passing. Still outstanding: PSI mobile has not been re-run, so the 86 baseline is untested. [Corrected 2026-08-14] This note originally ended "Nothing is committed or deployed." It was contradicted by its own commit, and by the post-deploy Lighthouse result recorded 47 lines above it. The gate numbers are left exactly as written: they are a dated build receipt, corroborated verbatim in wiki/log.md for the same date. The sitemap is 58 URLs today only because the publish gate releases scheduled pages daily; rewriting 55 to 58 would falsely attribute a 2026-08-14 count to a 2026-08-09 build.

Status as of 2026-08-14: what changed after this record was written

Everything above is left as the 2026-08-09 record, except where a bracketed correction marks a statement that was false on its own date. This block carries what has changed since. Verified against repo HEAD 37a9fda and live astrarad.com.

REOPENED A Seobility finding has partly come back

The rate-card and backlog CTAs are still fragments, exactly as the FIXED row describes. But 2a3e6bd (2026-08-11, "the form is the front door again") added two new /contact?ask=consult CTAs, one of them the above-the-fold hero button, at home.component.ts:181 and :629. The live homepage serves two of them today, and /contact is not disallowed in robots.txt, so the homepage again emits dynamic-parameter internal links. At 858fc2c it had zero. Converting them to /contact#consult is a two-line change, because the contact page already normalizes a fragment the same way it normalizes the query param.

The form select the fix was verified against no longer exists

e8f08d6 (2026-08-11) deleted the eight-option intent select outright. The fragment now drives the h1, the intro copy, the submit-button label and a hidden intent field instead. The SEO-load-bearing mechanism survives intact: the contact page still resolves normalizeAsk(params.get('ask') ?? fragment), so the legacy ?ask= still works and query still wins over fragment. This is worth stating because anyone re-verifying the fix today would go looking for a control that is gone and could wrongly conclude the fix regressed.

Two more third parties, both deferred

Microsoft Clarity (2510a43) and Leadfeeder (50eafc4) landed 2026-08-11, both deferred to the window load event in the same pattern as the gtag fix, so nothing returned to the critical path. This does change the PSI follow-up: an 86-to-X comparison now measures three changes rather than one, and the reading is only clean if it is taken before any further tracker lands.

Two measurement caveats on rows that still stand

Redirects. Both statements the row makes are single-hop and re-measure correctly. The composed form http://www.astrarad.com is two hops, because Netlify's TLS upgrade is host-preserving before the apex redirect. That is not the URL the tools were fed, and there is no repo-level control over it, so the N/A disposition is unchanged.

Nav contrast. The SIGNED half reproduces exactly: oklch 0.52 computes 5.10 to 1 on white, and the old 0.60 computes 3.69, both matching the row. The nav numbers do not reproduce from the stated colours alone. Against the header's own opaque #090e11 the new value computes 7.29 to 1, not 5.0, because the real header is 85.9 percent alpha with a backdrop blur, so Lighthouse's figure depends on whatever is composited underneath. Direction and pass/fail are unaffected.

Open action items this record now carries

  1. PSI mobile re-run, open five days. No lighthouse, psi or pagespeed result file exists anywhere in the repo, and no wiki log entry after 2026-08-09 mentions one. The stall is recorded: local Lighthouse on this VPS is noise, measuring TBT at 3,250ms on shared CPU against 40ms on PSI hardware, so the re-score waits on PSI quota.
  2. DONE 2026-08-14. Wired sameAs to the LinkedIn URL. One entry only, because it is the sole off-site profile whose URL is recorded and which was verified to resolve. Crunchbase and BBB are ticked done in DOCS/state/listing-progress.json but carry no URL, so they stay out until one is captured.
  3. DONE 2026-08-14. Address and legal name published. The founder re-supplied the filing verbatim, so the MedicalOrganization node now carries legalName "Astrarad LLC" and a PostalAddress for 8 The Green STE B, Dover, DE 19901. Deliberately still absent: foundingDate, and no LocalBusiness type, no geo and no openingHours on the org node, so nothing can read the registered address as a place a patient visits.
  4. DONE 2026-08-14. Both ?ask=consult CTAs converted to fragment="consult" at home.component.ts:181 and :629. The built homepage now emits zero ?ask= links and two /contact#consult. The ask-intent build gate passes, since consult was already one of the eight defined intents.
  5. Re-run Seobility once the three fixes above deploy, to confirm the dynamic-parameter and external-links findings actually close. No re-scan has been recorded since 2026-08-09.
  6. Re-measure backlinks before any link-buying decision. The 9 backlinks, 27 percent and Majestic vendor-anchor observations are still the only backlink record in the repo.
  7. Settle the operating-history claim. This one needs the founder, not an engineer. "More than ten years" appears 11 times across 8 files, including llms.txt, llms-full.txt, the organization schema description, /sla and /facts. It came from the founder directly, and the project already has a standing rule not to invent a founding year from it. But the Delaware LLC was filed 1 June 2020 and the site separately says "2.4 million reports signed since 2019", and 2020-06-01 is now going out on directory listings alongside the ten-year claim. The three statements can all be true of one business, since a filing date, a platform counter start and an operating history are three different things. They will not look that way to a buyer who checks. wiki/features/listing-kit.md has this recorded as needing a founder decision.