meta robot, lazy loading updated
This commit is contained in:
parent
9dec52711e
commit
cc08ba4af5
@ -69,7 +69,7 @@ export default function AccidentDetailsPage({ params }) {
|
||||
<div className="inner-box">
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<img src={service.mainImage} alt={service.title} />
|
||||
<img src={service.mainImage} alt={service.title} loading="lazy"/>
|
||||
</figure>
|
||||
</div>
|
||||
<div className="lower-content">
|
||||
|
||||
@ -50,7 +50,7 @@ export default function AccidentPage() {
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<Link href={`/accident/${service.slug}`} aria-label="Accident Image">
|
||||
<img src={service.mainImage} alt={service.title} />
|
||||
<img src={service.mainImage} alt={service.title} loading="lazy"/>
|
||||
</Link>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
@ -92,7 +92,7 @@ export default function AreaOfInjuryDetails({ params }) {
|
||||
<div className="content-one mb_60">
|
||||
{/* Main Image */}
|
||||
<figure className="image-box mb_40">
|
||||
<img src={service.mainImage} alt={altText} />
|
||||
<img src={service.mainImage} alt={altText} loading="lazy"/>
|
||||
</figure>
|
||||
<div className="text-box">
|
||||
<h2>{service.shortTitle}</h2>
|
||||
|
||||
@ -55,7 +55,7 @@ export default function AreaOfInjury() {
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<Link href={`/area-of-injury/${item.slug}`} aria-label="Area oF Injury Image Link">
|
||||
<img src={item.image} alt={altText} />
|
||||
<img src={item.image} alt={altText} loading="lazy"/>
|
||||
</Link>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
@ -82,6 +82,7 @@ export default function BlogDetails({ params }) {
|
||||
<img
|
||||
src={related.thumbnail}
|
||||
alt={related.title}
|
||||
loading="lazy"
|
||||
/>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
@ -29,7 +29,7 @@ export default function Blog() {
|
||||
<div className="inner-box">
|
||||
<figure className="image-box">
|
||||
<Link href={`/blog/${blog.slug}`} aria-label="Blog Image">
|
||||
<img src={blog.thumbnail} alt={blog.title} />
|
||||
<img src={blog.thumbnail} alt={blog.title} loading="lazy"/>
|
||||
</Link>
|
||||
</figure>
|
||||
<div className="lower-content">
|
||||
|
||||
@ -134,7 +134,7 @@ export default function ContactClient() {
|
||||
<h2>Mailing Address</h2>
|
||||
<div className="inner-box">
|
||||
<div className="icon-box">
|
||||
<img src="/assets/images/icons/icon-2.png" alt="" />
|
||||
<img src="/assets/images/icons/icon-2.png" alt="Address icon" />
|
||||
</div>
|
||||
<p>5 – 4335 Bloor Street West <br />Etobicoke, M9C 2A5</p>
|
||||
</div>
|
||||
|
||||
@ -64,7 +64,7 @@ export default function Home() {
|
||||
>
|
||||
<div className="inner-box w-100 pb-0">
|
||||
<div className="icon-box mb-3 mb-lg-0">
|
||||
<img src="/assets/images/covid/virtual.webp" alt="Virtual Therapy" />
|
||||
<img src="/assets/images/covid/virtual.webp" alt="Virtual Therapy" loading="lazy" />
|
||||
</div>
|
||||
<h3>VIRTUAL THERAPY</h3>
|
||||
<p>
|
||||
@ -88,7 +88,7 @@ export default function Home() {
|
||||
<div className="inner-box d-flex flex-column flex-lg-row-reverse align-items-lg-start w-100 pb-0" >
|
||||
|
||||
<div className="icon-box ml-lg-3 mb-3 mb-lg-0">
|
||||
<img src="/assets/images/covid/home.webp" alt="Home Therapy" />
|
||||
<img src="/assets/images/covid/home.webp" alt="Home Therapy" loading="lazy"/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@ -89,7 +89,7 @@ export default function ServiceDetailPage({ params }) {
|
||||
<div className="service-details-content">
|
||||
<div className="content-one mb_60">
|
||||
<figure className="image-box mb_40">
|
||||
<img src={service.bigImg} alt={altText} />
|
||||
<img src={service.bigImg} alt={altText} loading="lazy"/>
|
||||
</figure>
|
||||
<div
|
||||
className="service-details-description"
|
||||
|
||||
@ -22,7 +22,7 @@ export default function ServicesPage() {
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<Link href={`/etobicoke-treatment-service/${item.slug}`} aria-label="Etobicoke treatment service">
|
||||
<img src={item?.image} alt={item.alt} />
|
||||
<img src={item?.image} alt={item.alt} loading="lazy"/>
|
||||
</Link>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
@ -41,6 +41,7 @@ export default function Faq() {
|
||||
<img
|
||||
src="/assets/images/faq/img.webp"
|
||||
alt="Do You Have Any Physiotherapy Questions"
|
||||
loading="lazy"
|
||||
className="img-fluid"
|
||||
style={{ height: "550px", objectFit: "cover" }}
|
||||
/>
|
||||
|
||||
@ -24,13 +24,17 @@ export default function WhyChooseUs() {
|
||||
<>
|
||||
<section className="gallery-page-section sec-pad-2">
|
||||
<div className="auto-container">
|
||||
<div className="sec-title centred mb_50">
|
||||
<span className="sub-title">Gallery</span>
|
||||
<h2>Empowering Every Movement</h2>
|
||||
</div>
|
||||
<div className="row clearfix">
|
||||
{currentImages.map((src, index) => (
|
||||
<div key={index} className="col-lg-4 col-md-6 col-sm-12 gallery-block">
|
||||
<div className="gallery-block-one">
|
||||
<div className="inner-box">
|
||||
<figure className="image-box">
|
||||
<img src={src} alt={`gallery-${index}`} />
|
||||
<img src={src} alt={`gallery-${index}`} loading="lazy" />
|
||||
</figure>
|
||||
<div className="view-btn">
|
||||
<Link href={src} className="lightbox-image" data-fancybox="gallery" aria-label="View btn icon">
|
||||
|
||||
@ -36,6 +36,7 @@ export default function RootLayout({ children }) {
|
||||
|
||||
{/* ✅ Canonical Tag */}
|
||||
<link rel="canonical" href={canonicalUrl} aria-label="Site Url" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
{/* ✅ Open Graph Meta */}
|
||||
<meta property="og:title" content="Rapha Rehab – Physiotherapy Clinic" />
|
||||
|
||||
@ -27,6 +27,7 @@ export default function Home() {
|
||||
<img
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
loading="lazy"
|
||||
style={{ width: "410px", height: "444px", objectFit: "cover" }}
|
||||
/>
|
||||
</figure>
|
||||
|
||||
@ -61,7 +61,7 @@ export default function TeamDetails({ params }) {
|
||||
<div className="row clearfix">
|
||||
<div className="col-lg-5 col-md-12 col-sm-12 image-column">
|
||||
<figure className="image-box mr_15">
|
||||
<img src={member.imageDetail} alt={member.name} />
|
||||
<img src={member.imageDetail} alt={member.name} loading="lazy"/>
|
||||
</figure>
|
||||
</div>
|
||||
<div className="col-lg-7 col-md-12 col-sm-12 content-column">
|
||||
|
||||
@ -350,9 +350,9 @@ export default function RefugeeIFHP() {
|
||||
<div className="col-lg-6 col-md-12 col-sm-12 image-column">
|
||||
<div className="image_block_two">
|
||||
<div className="image-box">
|
||||
<figure className="image image-1-new"><img src="/assets/images/payment-insurance/back.webp" alt="Payment and Insurance" /></figure>
|
||||
<figure className="image image-2-new"><img src="/assets/images/payment-insurance/front.webp" alt="Payment and Insurance" /></figure>
|
||||
<div className="icon-box cart-icon"><img src="/assets/images/payment-insurance/icon.webp" alt="Payment and Insurance" /></div>
|
||||
<figure className="image image-1-new"><img src="/assets/images/payment-insurance/back.webp" alt="Payment and Insurance" loading="lazy"/></figure>
|
||||
<figure className="image image-2-new"><img src="/assets/images/payment-insurance/front.webp" alt="Payment and Insurance" loading="lazy"/></figure>
|
||||
<div className="icon-box cart-icon"><img src="/assets/images/payment-insurance/icon.webp" alt="Payment and Insurance" loading="lazy"/></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -64,7 +64,7 @@ export default function RehabilitationDetailsPage({ params }) {
|
||||
<div className="inner-box">
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<img src={service.mainImage} alt={service.title} />
|
||||
<img src={service.mainImage} alt={service.title} loading="lazy"/>
|
||||
</figure>
|
||||
</div>
|
||||
<div className="lower-content">
|
||||
|
||||
@ -51,7 +51,7 @@ export default function RehabilitationPage() {
|
||||
<div className="image-box">
|
||||
<figure className="image">
|
||||
<Link href={`/rehabilitation/${service.slug}`} aria-label="rehabilitation">
|
||||
<img src={service.mainImage} alt={service.title} />
|
||||
<img src={service.mainImage} alt={service.title} loading="lazy"/>
|
||||
</Link>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
135
package-lock.json
generated
135
package-lock.json
generated
@ -8,7 +8,7 @@
|
||||
"name": "start-app-dir",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.11.0",
|
||||
"axios": "^1.13.2",
|
||||
"framer-motion": "^12.23.12",
|
||||
"imagemin": "^9.0.1",
|
||||
"imagemin-avif": "^0.1.6",
|
||||
@ -23,8 +23,10 @@
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"react-modal-video": "^2.0.1",
|
||||
"sass": "^1.66.1",
|
||||
"selenium-webdriver": "^4.38.0",
|
||||
"swiper": "^10.2.0",
|
||||
"wowjs": "^1.1.3"
|
||||
"wowjs": "^1.1.3",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"next-export-optimize-images": "^4.7.0",
|
||||
@ -40,6 +42,12 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bazel/runfiles": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.5.0.tgz",
|
||||
"integrity": "sha512-RzahvqTkfpY2jsDxo8YItPX+/iZ6hbiikw1YhE0bA9EKBR5Og8Pa6FHn9PO9M0zaXRVsr0GFQLKbB/0rzy9SzA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@borewit/text-codec": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz",
|
||||
@ -1185,9 +1193,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
|
||||
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
@ -3506,6 +3514,12 @@
|
||||
"node": ">=14.16"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
|
||||
@ -3826,6 +3840,18 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
"dependencies": {
|
||||
"lie": "~3.3.0",
|
||||
"pako": "~1.0.2",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/junk": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz",
|
||||
@ -3853,6 +3879,15 @@
|
||||
"json-buffer": "3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.uniqwith": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz",
|
||||
@ -4852,6 +4887,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
@ -5334,7 +5375,6 @@
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
@ -5359,6 +5399,31 @@
|
||||
"seek-table": "bin/seek-bzip-table"
|
||||
}
|
||||
},
|
||||
"node_modules/selenium-webdriver": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.38.0.tgz",
|
||||
"integrity": "sha512-5/UXXFSQmn7FGQkbcpAqvfhzflUdMWtT7QqpEgkFD6Q6rDucxB5EUfzgjmr6JbUj30QodcW3mDXehzoeS/Vy5w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/SeleniumHQ"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/selenium"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@bazel/runfiles": "^6.3.1",
|
||||
"jszip": "^3.10.1",
|
||||
"tmp": "^0.2.5",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
@ -5406,6 +5471,12 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
|
||||
@ -5814,6 +5885,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/to-buffer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||
@ -6051,6 +6131,49 @@
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
||||
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
"postbuild": "npm run optimize-images"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.11.0",
|
||||
"axios": "^1.13.2",
|
||||
"framer-motion": "^12.23.12",
|
||||
"imagemin": "^9.0.1",
|
||||
"imagemin-avif": "^0.1.6",
|
||||
@ -28,8 +28,10 @@
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"react-modal-video": "^2.0.1",
|
||||
"sass": "^1.66.1",
|
||||
"selenium-webdriver": "^4.38.0",
|
||||
"swiper": "^10.2.0",
|
||||
"wowjs": "^1.1.3"
|
||||
"wowjs": "^1.1.3",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"next-export-optimize-images": "^4.7.0",
|
||||
|
||||
97
scripts/image_alt_issues.csv
Normal file
97
scripts/image_alt_issues.csv
Normal file
@ -0,0 +1,97 @@
|
||||
Page URL,Image Src,Alt Text,Issue Type
|
||||
"http://localhost:3000/","","rapharehab logo","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/","","Decorative Shape","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/","","Physiotherapy Icon","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/why-rapha-physiotherapy-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/why-rapha-physiotherapy-etobicoke/","","Physiotherapy at Rapharehab","Duplicate Alt (6 times)"
|
||||
"http://localhost:3000/why-rapha-physiotherapy-etobicoke/","","health care professionals","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/why-rapha-physiotherapy-etobicoke/","","Top-Notch Treatment","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/faq-physiotherapy-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/what-to-expect/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/what-to-expect/","","Physiotherapy at Rapharehab","Duplicate Alt (7 times)"
|
||||
"http://localhost:3000/payment-insurance/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/payment-insurance/","","Payment and Insurance","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/locations/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/about-us/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/about-us/","","Physiotherapy at Rapharehab","Duplicate Alt (19 times)"
|
||||
"http://localhost:3000/ourapproach-physiotherapy-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/ourapproach-physiotherapy-etobicoke/","","Physiotherapy at Rapharehab","Duplicate Alt (8 times)"
|
||||
"http://localhost:3000/our-team-physiotherapy-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/gallery-physiotherapy-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/covid-19-updates/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Osteopathy Clinic In Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Massage Therapy Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Acupuncture Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Chiropodist Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Chiropractic Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","orthotics in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","foot reflexology clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","custom knee braces clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","laser therapy electrical modalities | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","virtual care physiotherapy clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","naturopathy clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","spinal decompression therapy clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","concussion management clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Chronic Pain Management Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","prepost operative management clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","ExerciseTherapy Clinic In Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Workplace Injury Management Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","pelvic floor physiotherapy clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","home care physiotherapy clinic in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Sports Injury Physiotherapy Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Gait Assessment | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","kids physiotherapy in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","surgical rehab in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Physiotherapy Clinic in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Fascial Stretch Therapy in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","cupping therapy in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Shiatsu Therapy in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Deep Tissue Massage in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","neuro fascial therapy in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Cranio Sacral Therapy in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","motor vehicle accident rehabilitation in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Compression Stockings in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Cardiac Rehabilitation in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Intramuscular Stimulation IMS in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Psychotherapy in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","Shockwave Therapy in Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/","","refugee in etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/area-of-injury/","","HEAD INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","NECK INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","SHOULDER INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","ELBOW INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","WRIST & HAND INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","LOW BACK INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","HIP INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","LEG & KNEE INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/","","ANKLE & FOOT INJURIES","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/rehabilitation/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/accident/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/accident/","","Minor Injury","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Catastrophic Injury","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Slip and Fall Injury","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Concussion Management","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Psychotherapy Management","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Hydrotherapy","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/","","Chronic Pain Management","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/blog/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/contact/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/caregivers/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/caregivers/","","Physiotherapy at Rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/shortcodes/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/shortcodes/","","Physiotherapy at Rapharehab","Duplicate Alt (6 times)"
|
||||
"http://localhost:3000/shortcodes/","","Why choose nanocare","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/blog/chronic-pain-treatment-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/blog/chronic-pain-treatment-etobicoke/","","How Does Rapharehab - Physiotherapy in Etobicoke Treat Chronic Pain Conditions?","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/","","OSTEOPATHY IN ETOBICOKE","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/","","Osteopathy Clinic In Etobicoke | Rapharehab","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/area-of-injury/head-injury-physiotherapy-management-in-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/area-of-injury/head-injury-physiotherapy-management-in-etobicoke/","","HEAD INJURIES","Duplicate Alt (5 times)"
|
||||
"http://localhost:3000/rehabilitation/spinalcord-rehabilitation-clinic-in-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/rehabilitation/spinalcord-rehabilitation-clinic-in-etobicoke/","","Spinal Cord Injury Rehabilitation","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/accident/minor-injury-care-in-etobicoke/","","rapharehab","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/accident/minor-injury-care-in-etobicoke/","","Minor Injury","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/our-team-physiotherapy-etobicoke/dhanya-prashant/","","rapharehab","Duplicate Alt (3 times)"
|
||||
|
266
scripts/seo-test-selenium.cjs
Normal file
266
scripts/seo-test-selenium.cjs
Normal file
@ -0,0 +1,266 @@
|
||||
// 🚀 Full SEO + Broken Link + 404 + Accessibility + Image Alt CSV Export
|
||||
// Run with: node seo_full_audit.js
|
||||
|
||||
const { Builder, By } = require("selenium-webdriver");
|
||||
const chrome = require("selenium-webdriver/chrome");
|
||||
const axios = require("axios");
|
||||
const xml2js = require("xml2js");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// CSV file for Image Alt issues
|
||||
const csvPath = path.join(__dirname, "image_alt_issues.csv");
|
||||
fs.writeFileSync(csvPath, "Page URL,Image Src,Alt Text,Issue Type\n", "utf8");
|
||||
|
||||
// ==========================
|
||||
// 1️⃣ Fetch URLs from sitemap.xml
|
||||
// ==========================
|
||||
async function getUrlsFromSitemap(sitemapUrl) {
|
||||
try {
|
||||
const res = await axios.get(sitemapUrl);
|
||||
const parsed = await xml2js.parseStringPromise(res.data);
|
||||
return parsed.urlset.url.map((u) => u.loc[0]);
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to load sitemap:", err.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 2️⃣ Check HTTP Status
|
||||
// ==========================
|
||||
async function checkLinkStatus(url) {
|
||||
try {
|
||||
const res = await axios.get(url, {
|
||||
timeout: 10000,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
|
||||
if (
|
||||
res.status === 200 &&
|
||||
(
|
||||
/404/i.test(res.data.match(/<title[^>]*>(.*?)<\/title>/)?.[1] ?? "")
|
||||
)
|
||||
) {
|
||||
return "Soft 404";
|
||||
}
|
||||
|
||||
return res.status;
|
||||
} catch (err) {
|
||||
return err.response ? err.response.status : "❌ No Response";
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 3️⃣ Main SEO + Accessibility + Image Alt Audit
|
||||
// ==========================
|
||||
async function checkSEO(url, siteDomain) {
|
||||
const options = new chrome.Options();
|
||||
options.addArguments("--headless", "--no-sandbox", "--disable-gpu");
|
||||
|
||||
const driver = await new Builder()
|
||||
.forBrowser("chrome")
|
||||
.setChromeOptions(options)
|
||||
.build();
|
||||
|
||||
try {
|
||||
const pageStatus = await checkLinkStatus(url);
|
||||
if (pageStatus === 404 || pageStatus === "Soft 404") {
|
||||
console.log(`\n🚫 ${url} → ❌ Page not found (${pageStatus})`);
|
||||
return;
|
||||
}
|
||||
|
||||
await driver.get(url);
|
||||
const pageSource = await driver.getPageSource();
|
||||
|
||||
// Basic SEO Elements
|
||||
const title = await driver.getTitle();
|
||||
const descElem = await driver.findElements(By.css('meta[name="description"]'));
|
||||
const canonicalElem = await driver.findElements(By.css('link[rel="canonical"]'));
|
||||
const robotsElem = await driver.findElements(By.css('meta[name="robots"]'));
|
||||
const viewportElem = await driver.findElements(By.css('meta[name="viewport"]'));
|
||||
const charset = await driver.findElements(By.css('meta[charset]'));
|
||||
const htmlTag = await driver.findElement(By.css("html"));
|
||||
const langAttr = await htmlTag.getAttribute("lang").catch(() => "");
|
||||
const h1Tags = await driver.findElements(By.css("h1"));
|
||||
const h2Tags = await driver.findElements(By.css("h2"));
|
||||
|
||||
// Meta Description
|
||||
let descContent = descElem.length > 0 ? await descElem[0].getAttribute("content") : "";
|
||||
const descLength = descContent.length;
|
||||
const descStatus =
|
||||
descLength === 0
|
||||
? "❌ Missing"
|
||||
: descLength < 50
|
||||
? `⚠️ Too short (${descLength})`
|
||||
: descLength > 160
|
||||
? `⚠️ Too long (${descLength})`
|
||||
: "✅ Perfect";
|
||||
|
||||
// Title length check
|
||||
const titleLength = title.length;
|
||||
const titleStatus =
|
||||
titleLength === 0
|
||||
? "❌ Missing"
|
||||
: titleLength < 30
|
||||
? `⚠️ Too short (${titleLength})`
|
||||
: titleLength > 65
|
||||
? `⚠️ Too long (${titleLength})`
|
||||
: "✅ Perfect";
|
||||
|
||||
// Canonical
|
||||
const canonicalURL =
|
||||
canonicalElem.length > 0 ? await canonicalElem[0].getAttribute("href") : "❌ Missing";
|
||||
|
||||
// 🖼️ Image Accessibility Audit
|
||||
const imgs = await driver.findElements(By.css("img"));
|
||||
let missingAlt = 0;
|
||||
let emptyAlt = 0;
|
||||
let duplicateAlt = [];
|
||||
const altTextMap = new Map();
|
||||
|
||||
for (const img of imgs) {
|
||||
const src = await img.getAttribute("src");
|
||||
const alt = (await img.getAttribute("alt"))?.trim() ?? null;
|
||||
|
||||
if (alt === null) {
|
||||
missingAlt++;
|
||||
fs.appendFileSync(csvPath, `"${url}","${src}","","Missing Alt"\n`, "utf8");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (alt === "") {
|
||||
emptyAlt++;
|
||||
fs.appendFileSync(csvPath, `"${url}","${src}","(empty)","Empty Alt"\n`, "utf8");
|
||||
}
|
||||
|
||||
if (altTextMap.has(alt)) {
|
||||
altTextMap.set(alt, altTextMap.get(alt) + 1);
|
||||
} else {
|
||||
altTextMap.set(alt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [altText, count] of altTextMap.entries()) {
|
||||
if (altText && count > 1) {
|
||||
duplicateAlt.push({ altText, count });
|
||||
fs.appendFileSync(
|
||||
csvPath,
|
||||
`"${url}","","${altText}","Duplicate Alt (${count} times)"\n`,
|
||||
"utf8"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect tracking & schema tags
|
||||
const hasGTM = pageSource.includes("googletagmanager.com/gtm.js");
|
||||
const hasClarity = pageSource.includes("clarity.ms/tag");
|
||||
const hasFBPixel = pageSource.includes("fbevents.js") || pageSource.includes("fbq(");
|
||||
const hasAnalytics = pageSource.includes("www.googletagmanager.com/gtag/js");
|
||||
|
||||
const ogTags = await driver.findElements(By.css("meta[property^='og:']"));
|
||||
const twitterTags = await driver.findElements(By.css("meta[name^='twitter:']"));
|
||||
const schemaScripts = await driver.findElements(By.css('script[type="application/ld+json"]'));
|
||||
|
||||
// Links check
|
||||
const anchorTags = await driver.findElements(By.css("a[href]"));
|
||||
const brokenLinks = [];
|
||||
for (const a of anchorTags) {
|
||||
const href = await a.getAttribute("href");
|
||||
if (!href || href.startsWith("#") || href.startsWith("mailto:")) continue;
|
||||
|
||||
const fullUrl = href.startsWith("http")
|
||||
? href
|
||||
: `${siteDomain}${href.startsWith("/") ? href : `/${href}`}`;
|
||||
|
||||
if (fullUrl.includes(siteDomain)) {
|
||||
const status = await checkLinkStatus(fullUrl);
|
||||
if (status === 404 || status === "Soft 404" || status === "❌ No Response") {
|
||||
brokenLinks.push({ link: fullUrl, status });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy loading check
|
||||
const images = await driver.findElements(By.css("img, video, iframe"));
|
||||
const lazyLoadCount = await Promise.all(
|
||||
images.map(async (img) => {
|
||||
const loading = await img.getAttribute("loading");
|
||||
return loading === "lazy";
|
||||
})
|
||||
);
|
||||
const lazyLoaded = lazyLoadCount.filter((v) => v).length;
|
||||
|
||||
// Console Summary
|
||||
console.log(`\n🔍 Checking: ${url}`);
|
||||
console.log("-------------------------------------------");
|
||||
console.log("Title:", titleStatus);
|
||||
console.log("Meta Description:", descStatus);
|
||||
console.log("Canonical URL:", canonicalURL);
|
||||
console.log("Meta Robots:", robotsElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Viewport:", viewportElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Charset:", charset.length > 0 ? "✅ Found" : "❌ Missing");
|
||||
console.log("HTML lang:", langAttr ? `✅ ${langAttr}` : "⚠️ Missing");
|
||||
console.log("H1 Tags:", h1Tags.length > 0 ? `✅ ${h1Tags.length}` : "❌ Missing");
|
||||
console.log("H2 Tags:", h2Tags.length > 0 ? `ℹ️ ${h2Tags.length}` : "⚠️ None");
|
||||
console.log("Images:", imgs.length);
|
||||
console.log(
|
||||
"Missing Alt:",
|
||||
missingAlt > 0 ? `❌ ${missingAlt}` : "✅ None"
|
||||
);
|
||||
console.log(
|
||||
"Empty Alt:",
|
||||
emptyAlt > 0 ? `⚠️ ${emptyAlt}` : "✅ None"
|
||||
);
|
||||
console.log(
|
||||
"Duplicate Alt:",
|
||||
duplicateAlt.length > 0 ? `⚠️ ${duplicateAlt.length}` : "✅ None"
|
||||
);
|
||||
console.log("Lazy Loaded Images:", lazyLoaded > 0 ? `✅ ${lazyLoaded}` : "⚠️ None");
|
||||
console.log("Open Graph Tags:", ogTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Twitter Tags:", twitterTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Schema Markup:", schemaScripts.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Google Analytics:", hasAnalytics ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("GTM:", hasGTM ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Clarity:", hasClarity ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Facebook Pixel:", hasFBPixel ? "✅ Found" : "⚠️ Missing");
|
||||
|
||||
if (brokenLinks.length > 0) {
|
||||
console.log("\n❌ Broken Links:");
|
||||
brokenLinks.forEach((b) => console.log(` → ${b.link} [${b.status}]`));
|
||||
} else {
|
||||
console.log("✅ No broken links found.");
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error(`❌ Error on ${url}:`, err.message);
|
||||
} finally {
|
||||
await driver.quit();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 4️⃣ Run Full Site Audit
|
||||
// ==========================
|
||||
(async () => {
|
||||
const sitemapUrl = "https://rapharehab.ca/sitemap.xml";
|
||||
const siteDomain = "http://localhost:3000";
|
||||
|
||||
console.log("📄 Fetching URLs from sitemap...");
|
||||
const urls = await getUrlsFromSitemap(sitemapUrl);
|
||||
|
||||
if (urls.length === 0) {
|
||||
console.error("❌ No URLs found in sitemap.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ Found ${urls.length} URLs in sitemap.`);
|
||||
console.log("🚀 Starting Full SEO + Accessibility + Broken Link Audit...");
|
||||
|
||||
for (const url of urls) {
|
||||
await checkSEO(url, siteDomain);
|
||||
}
|
||||
|
||||
console.log("\n✅ Full SEO Audit Completed!");
|
||||
console.log(`📁 CSV Report: ${csvPath}`);
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user