All 7 pages of the live site checked the way Google and AI assistants read them: speed on phone and desktop, HTML structure, structured data, images, video, links, AI-agent access.
Two things hold the site back: the English page tells Google its address is the bare domain instead of /en/ (the single item Lighthouse fails), and every visit downloads 11.4 MB (a 5.2 MB autoplay video plus 7.6 MB of uncompressed images), which drops desktop performance to 52.
Below: three tables, one task per row, with time and budget. Technical details under a task opens the page lists and code. Total 37.5 hours, $1,500.
http to https and www to the bare domain return a proper 301, so there is one address for the site.| # | Task | What to do | What it affects | Why it matters | Budget · Time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Point the English page canonical at itself | On /en/ change the canonical, og:url and twitter:url from https://axyglobal.com/ to https://axyglobal.com/en/. The Russian page already does this correctly, so copy its pattern. |
Google rankings · Index quality · Which page shows in results | A canonical tag tells Google the real address of a page. Right now the English page says its real address is the bare domain, which serves a 239 byte holding page with no content, so Google is being asked to index a blank page instead of the site. This is the only item Lighthouse fails in its SEO check. | $401 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical detailsLighthouse verdict on both mobile and desktop: "Document does not have a valid rel=canonical. Points to the domain's root URL (the homepage), instead of an equivalent page of content."
The same three tags on
This also contradicts the hreflang block on the same page, which correctly lists | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2 | Replace the root page with a real 301 redirect | Delete the holding page at / and add a _redirects file to the Netlify deploy with / /en/ 301. Keep a language check later if you want, but the default must be a server redirect, not an HTML page. |
Google rankings · Index quality · Speed on first visit | The bare domain currently answers with a tiny HTML page that uses a meta refresh to bounce visitors to /en/. Google treats this as a weak signal rather than a clean move, and every visitor pays for two page loads instead of one. This is also the address the English page names as its canonical, so the two problems compound. |
$601.5 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details
That page has no canonical, no description, no hreflang and no content. Because it answers 200 rather than 301, Google can index it as a separate URL competing with
Note the second row: a visitor typing | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 3 | Publish robots.txt and sitemap.xml | Add robots.txt and sitemap.xml to the deploy root. The sitemap should list /en/ and /ru/ with their hreflang pairs. Reference the sitemap from robots.txt, then submit it in Google Search Console and Bing Webmaster Tools. |
Google rankings · Index quality · AI answers | Both files are missing and the server answers with Netlify's "Page not found" screen. Search engines and AI crawlers look for them on every visit and find nothing, so there is no list of pages to crawl and no way to steer the crawl. For a site this small a sitemap is a ten line file that removes all guesswork. | $802 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details
Because The seven addresses that should be covered:
Worth knowing: a | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 4 | Stop loading Tailwind from the CDN | Remove <script src="https://cdn.tailwindcss.com"> and build the stylesheet at deploy time with the Tailwind CLI, then link the compiled CSS file. The visual result is identical. |
Desktop speed · Mobile speed · Google rankings | That script downloads the whole Tailwind engine and builds the site's CSS inside the visitor's browser on every single visit. It is the reason the browser sits blocked for 1,850 ms on desktop and why desktop performance is 52, worse than mobile. Tailwind's own documentation states this script is for trying things out and must not be used on a live site. | $1203 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details
Scripts loaded from other people's servers, 9 script requests totalling 792 KB:
Two icon libraries are loaded for one page. Compiling Tailwind ahead of time also removes the 18 KB of unused CSS rules Lighthouse reports, because the build step strips every class the site does not use. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 5 | Compress the 5.2 MB banner video | Re-encode banner.mp4 to H.264 at a sensible bitrate and add a WebM version, target under 800 KB. Add a poster image so something appears instantly, and drop autoplay on mobile in favour of the poster. |
Mobile speed · Google rankings · Mobile data cost | The hero video is 5.18 MB and starts downloading and playing the moment the page opens. It is nearly half the page weight and the main reason the largest element on mobile takes 5.1 seconds to appear. Visitors on a phone connection pay for it before they read a single word. | $802 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details
Current markup:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 6 | Convert 7.6 MB of images to WebP | Convert all 30 images to WebP at quality 80 and serve them through a <picture> element with a JPEG fallback. The five files over 500 KB are the priority. Photographs saved as PNG are the main waste. |
Mobile speed · Desktop speed · Google rankings | Not one image on the site uses a modern format: 29 are JPEG and 20 are PNG. Team photos and screenshots are saved as PNG, which is built for flat graphics and roughly triples the size of a photograph. Converting them typically removes 60 to 80 percent of the weight with no visible difference. | $1203 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details30 unique images, 7.59 MB total, 0 in WebP or AVIF. 9 files are over 200 KB and 5 are over 500 KB.
Remaining 12 files are each under 90 KB and account for the balance of the 7.59 MB. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 7 | Add lazy loading and size attributes to images | Add width and height to the 41 image tags that lack them, and loading="lazy" plus decoding="async" to every image below the first screen. Leave the logo and hero eager. |
Mobile speed · Google rankings · Mobile data cost | Only 10 of 51 images wait until they are scrolled into view, so the browser fetches team photos and case screenshots that most visitors never reach. Declared width and height let the browser reserve the right space before the file arrives, which protects the layout stability the site currently has. | $601.5 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical details
Layout shift is currently 0 because Tailwind aspect ratio classes hold the space. Once the CDN script is replaced in task 4 that protection depends on the compiled CSS shipping those same classes, so adding real | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 8 | Put the 10 services into the HTML | Render the servicesData cards into the page source at build time instead of creating them with document.createElement after load. Keep the click-to-open popup behaviour in JavaScript, but the names and descriptions must exist in the HTML. |
AI answers · Google rankings · Index quality | All ten service names are built by a script after the page loads. Google will usually run that script, but ChatGPT, Perplexity and Claude read the raw HTML and do not. So when someone asks an AI assistant for an Amazon or TikTok Shop agency, the ten phrases that describe exactly what AXY sells are invisible to it. | $1203 h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Technical detailsThe services grid is filled in by this loop, so the titles only exist inside a JavaScript template string:
Counting headings with scripts stripped out shows the gap between what a text-only crawler sees and what a browser sees:
The ten service names missing from the static HTML, each one a phrase people actually search for:
The case study details behind the ten portfolio cards live in a second script array, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Critical subtotal · 17 hours | $680 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | Task | What to do | What it affects | Why it matters | Budget · Time | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 9 | Write real copy for the services and cases | Expand the page past 1,000 words of genuine text, or split the ten services into their own pages. Each service needs a paragraph explaining what is delivered, for whom, and what the result looks like. Each case needs the numbers spelled out in text, not only inside a screenshot. | Google rankings · AI answers · Conversion | The whole page holds 316 words once rendered. Competing agency sites answer specific questions across many pages, so Google has far more to match a search against than AXY offers. Results are currently shown as image screenshots, which neither Google nor an AI assistant can read as evidence. | $1604 h | ||||||||||||||||||||||||
Technical details
The ten portfolio cards are headed only by a product category (Mushroom-Shaped Humidifier, Auto Parts (LED Bulbs), Kids Furniture, Diamond Painting, Beauty Brand, DIY Craft Kits, Fashion Apparel, Firearm Accessories, Toys & Hobby, Jewelry). The revenue figures behind them sit in the Ten separate service pages would also give the site something it has none of today: internal links between pages. Every one of the 30 internal links on the page is a jump to a section of the same page. | |||||||||||||||||||||||||||||
| 10 | Fill out the company schema | Extend the JSON-LD block: switch @type from Corporation to ProfessionalService, add sameAs with the LinkedIn, Instagram and Facebook URLs already in the footer, plus address, telephone, foundingDate and founder. |
AI answers · Trust · Rich results | AI assistants read company facts from this block rather than from the page text. Today it carries six fields and no link to any social profile, so an assistant asked "who is AXY Marketing" has nothing to confirm the company is real or connect it to its LinkedIn presence. The social links are already on the page and just need listing in the code. | $601.5 h | ||||||||||||||||||||||||
Technical detailsThe page carries exactly one JSON-LD block. It is valid but minimal:
The social profiles to list in | |||||||||||||||||||||||||||||
| 11 | Add FAQ, Service and WebSite structured data | Add a visible FAQ section with six to eight real questions and mark it up as FAQPage. Add a Service block for each of the ten services and one WebSite block with the site name. |
AI answers · AI shopping assistants · Rich results | None of these exist today. AI assistants answer questions by quoting content already shaped as a question and answer, so a page with no FAQ rarely gets cited. Buyers ask the same things every time: what it costs, how long a launch takes, which countries you cover, what happens if it does not work. | $802 h | ||||||||||||||||||||||||
Technical detailsStructured data present across all 7 pages of the site:
The four policy pages carry no structured data at all, which is fine since they are set to noindex. The two services already described inside | |||||||||||||||||||||||||||||
| 12 | Give the 22 buttons accessible names | Add aria-label to the 19 buttons that have none. The mobile menu button, the popup close buttons and the case detail buttons are the ones Lighthouse names. |
Accessibility · AI understanding of pages · Mobile usability | Buttons that contain only an icon have no text for a screen reader or a crawler to read, so they announce as "button" with no purpose. Lighthouse fails this outright on mobile and it is one of the four reasons the accessibility score sits at 80. | $601.5 h | ||||||||||||||||||||||||
Technical details22 Accessibility score by device and the audits behind it:
Separately, 13 links and buttons are smaller than the 44 by 44 pixel minimum on a 390 pixel wide screen, including the mobile menu button and the case detail buttons. | |||||||||||||||||||||||||||||
| 13 | Allow visitors to zoom on mobile | Change the viewport tag to width=device-width, initial-scale=1.0 by removing maximum-scale=1.0 and user-scalable=no. |
Accessibility · Mobile usability · Google rankings | The page currently blocks pinch to zoom on phones. Anyone who needs to enlarge text to read it cannot, and Lighthouse fails this on both mobile and desktop. It is a two word deletion. | $200.5 h | ||||||||||||||||||||||||
Technical detailsCurrent tag on
Lighthouse: "[user-scalable="no"] is used in the meta name="viewport" element ... user-scalable=no on meta tag disables text scaling." The four policy pages already use the correct short form, so only the two main pages need editing. | |||||||||||||||||||||||||||||
| 14 | Fix the heading order | Change the footer headings ("Navigation", "Contacts", "Contact Us") from h4 to h3, and review the 41 h4 elements so no heading skips a level below its parent h2. |
Accessibility · AI understanding of pages · Google rankings | The page jumps straight from an h2 to an h4 with nothing in between, so the outline reads as though a section is missing. Search engines and AI assistants use that outline to work out which parts of the page belong together, and screen readers use it to navigate. | $401 h | ||||||||||||||||||||||||
Technical detailsHeading counts on Lighthouse There are 41 h4 elements against 19 h3, an inverted shape. Normally the deeper level is the rarer one. Most of the h4 count comes from the service and case popups. Two empty h3 elements exist, | |||||||||||||||||||||||||||||
| 15 | Add the missing security headers | Add a Netlify _headers file setting Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy and Permissions-Policy. Extend the existing HSTS header with includeSubDomains and preload. |
Trust · Security · Index quality | The server sends only one security header today. Without X-Frame-Options another site can load AXY inside a frame and pass it off as their own, and without X-Content-Type-Options a browser can be tricked into running a file as a script. None of this changes how the site looks. |
$601.5 h | ||||||||||||||||||||||||
Technical details
Write the CSP after task 4 lands, since removing the Tailwind CDN and the two icon libraries shortens the list of allowed sources considerably. Set it to report only for a week before enforcing. | |||||||||||||||||||||||||||||
| 16 | Remove the duplicate Clarity tag | Delete one of the two Microsoft Clarity snippets in the head. Decide which project ID is the live one, keep that, remove the other. | Mobile speed · Data accuracy | Two separate Clarity trackers load on every page view, each opening its own connection and recording the same session twice. One of them is collecting data nobody looks at, and both slow the page down. | $200.5 h | ||||||||||||||||||||||||
Technical detailsTwo identical Clarity loader blocks sit back to back in the head of both
Other tracking on the page, all correctly installed once: Google Tag Manager 23 of the 50 requests on the page go to third party domains, totalling 1,007 KB. | |||||||||||||||||||||||||||||
| 17 | Fix the run-together words in the main heading | In the h2 "We Impact Specific Metrics and<br>Increase Your Net Profit in Your Pocket", add a space before the line break so the text reads correctly when the markup is stripped. | Google rankings · AI answers · Trust | A line break sits directly between two words with no space, so every system that reads the page as plain text sees "andIncrease" as one word. That includes Google, AI assistants and screen readers. On screen it looks fine, which is why it has gone unnoticed. | $200.5 h | ||||||||||||||||||||||||
Technical detailsCurrent markup:
Extracted text: Fix by putting a space before | |||||||||||||||||||||||||||||
| 18 | Fix contrast on the WhatsApp and Telegram buttons | Darken the green and blue backgrounds on the messenger buttons, or switch their label text to a darker colour, until the contrast ratio reaches 4.5 to 1. | Accessibility · Conversion · Mobile usability | White text on the current green and light blue backgrounds falls below the readable minimum, and Lighthouse fails it on mobile. These two buttons are the main way to start a conversation, so they are the worst place on the site to have text that is hard to read in daylight. | $401 h | ||||||||||||||||||||||||
Technical detailsLighthouse
Tailwind | |||||||||||||||||||||||||||||
| 19 | Rename the "Tik tok" image folder | Rename portfolio/Tik tok/ to portfolio/tiktok/ and update the four image paths that point into it. |
Google Images · Index quality | The folder name contains a space and a capital letter, so every URL inside it is served as Tik%20tok. Encoded spaces in paths are a common source of broken links when URLs get copied, shared or rewritten, and they make the filename useless as a description of the image. |
$401 h | ||||||||||||||||||||||||
Technical detailsAffected files, all reachable but only via the encoded form:
Do this at the same time as the WebP conversion in task 6, since those three files are being rewritten anyway. Descriptive names such as | |||||||||||||||||||||||||||||
| Medium subtotal · 15 hours | $600 | ||||||||||||||||||||||||||||
| # | Task | What to do | What it affects | Why it matters | Budget · Time | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20 | Drop the third party icon libraries | Replace Font Awesome and Lucide with inline SVG for the icons actually used, or self host a subset. If Lucide stays, pin it to a fixed version instead of @latest. |
Mobile speed · Security · Reliability | Two separate icon libraries load from two outside servers for a handful of icons. Loading @latest means whatever the library authors publish tomorrow runs on the site automatically, with no review, and if either server is slow or down the page waits on it. |
$601.5 h | ||||||||||||||||||||||||||||||
Technical details
Font loading accounts for 186 KB across 3 requests, most of it icon fonts rather than text fonts. The page declares only 2 preconnect hints and no preload, so each third party host costs a fresh DNS lookup and TLS handshake before anything downloads. | |||||||||||||||||||||||||||||||||||
| 21 | Publish an llms.txt file | Add /llms.txt describing the company, the ten services, the markets served and how to get in touch, in plain Markdown. |
AI answers · AI shopping assistants | A growing number of AI assistants check this file first to understand what a site offers before reading the pages. It costs one file and gives AXY a controlled summary in the exact form assistants prefer, instead of leaving them to guess from a page whose services load by script. | $401 h | ||||||||||||||||||||||||||||||
Technical details
Worth pairing with task 8. If the services move into the HTML and an llms.txt lists them as well, the ten service phrases become readable by every assistant whether or not it runs JavaScript. | |||||||||||||||||||||||||||||||||||
| 22 | Give the policy pages descriptions and canonicals | Add a meta description and a self referencing canonical to all four policy pages. Change noindex, nofollow to noindex, follow. |
Trust · Index quality | The four policy pages have no description and no canonical. The nofollow part also tells search engines to ignore every link on those pages, including the ones back to the main site, which serves no purpose. |
$401 h | ||||||||||||||||||||||||||||||
Technical details
These pages also carry no hreflang, so the English and Russian versions of the same policy are not linked to each other. Low impact while they stay noindex, but worth adding in the same pass. | |||||||||||||||||||||||||||||||||||
| 23 | Publish a phone number and an address | Add a clickable tel: link and a business address to the footer, then mirror both into the company schema from task 10. |
Trust · AI answers · Conversion | The site offers an email address and two messenger links but no phone number and no location of any kind. For an agency asking clients to hand over an Amazon account, that absence is the first thing a careful buyer notices, and it leaves AI assistants unable to say where the company is based. | $401 h | ||||||||||||||||||||||||||||||
Technical details
The WhatsApp number is a Ukrainian mobile. If the company presents itself as US facing, publishing the registered entity and country removes an obvious question rather than creating one. | |||||||||||||||||||||||||||||||||||
| 24 | Clean up the three dead links | Find the three anchors with href="#" and either point them at a real section or turn them into buttons. Add rel="noopener noreferrer" to the two external links that lack it. |
Index quality · Security · Conversion | A link to # jumps the visitor back to the top of the page, which reads as a broken link. Separately, two links open in a new tab without rel="noopener", which lets the opened page take control of the tab it came from. |
$200.5 h | ||||||||||||||||||||||||||||||
Technical details3 anchors use External links opening in a new tab without
The same two destinations appear elsewhere on the page correctly carrying | |||||||||||||||||||||||||||||||||||
| 25 | Remove the emoji from the h1 and the keywords tag | Delete the rocket emoji from the start of the h1 so the heading opens on the words that matter, and remove the obsolete <meta name="keywords"> tag from both pages. |
Google rankings · Click-through from Google · Trust | The h1 is the strongest single signal of what a page is about, and it currently opens with a decoration instead of a keyword. The keywords tag has been ignored by Google since 2009 and does nothing except publish your target keyword list to competitors. | $200.5 h | ||||||||||||||||||||||||||||||
Technical detailsCurrent h1 on Current keywords tag: Both pages carry exactly one h1, which is correct. The title tag itself is well formed at 63 characters on English and 67 on Russian, slightly over the 60 character mark where Google starts truncating, so trimming a few words there is worth doing in the same pass.
| |||||||||||||||||||||||||||||||||||
| Low, but worth doing subtotal · 5.5 hours | $220 | ||||||||||||||||||||||||||||||||||