meta robot, lazy loading updated

This commit is contained in:
Selvi 2025-11-22 17:51:18 +05:30
parent 9dec52711e
commit cc08ba4af5
22 changed files with 524 additions and 28 deletions

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -82,6 +82,7 @@ export default function BlogDetails({ params }) {
<img
src={related.thumbnail}
alt={related.title}
loading="lazy"
/>
</figure>
</div>

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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" }}
/>

View File

@ -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">

View File

@ -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" />

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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">

View File

@ -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
View File

@ -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",

View File

@ -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",

View 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)"
1 Page URL Image Src Alt Text Issue Type
2 http://localhost:3000/ rapharehab logo Duplicate Alt (2 times)
3 http://localhost:3000/ Decorative Shape Duplicate Alt (3 times)
4 http://localhost:3000/ Physiotherapy Icon Duplicate Alt (2 times)
5 http://localhost:3000/why-rapha-physiotherapy-etobicoke/ rapharehab Duplicate Alt (3 times)
6 http://localhost:3000/why-rapha-physiotherapy-etobicoke/ Physiotherapy at Rapharehab Duplicate Alt (6 times)
7 http://localhost:3000/why-rapha-physiotherapy-etobicoke/ health care professionals Duplicate Alt (3 times)
8 http://localhost:3000/why-rapha-physiotherapy-etobicoke/ Top-Notch Treatment Duplicate Alt (3 times)
9 http://localhost:3000/faq-physiotherapy-etobicoke/ rapharehab Duplicate Alt (3 times)
10 http://localhost:3000/what-to-expect/ rapharehab Duplicate Alt (3 times)
11 http://localhost:3000/what-to-expect/ Physiotherapy at Rapharehab Duplicate Alt (7 times)
12 http://localhost:3000/payment-insurance/ rapharehab Duplicate Alt (3 times)
13 http://localhost:3000/payment-insurance/ Payment and Insurance Duplicate Alt (3 times)
14 http://localhost:3000/locations/ rapharehab Duplicate Alt (3 times)
15 http://localhost:3000/about-us/ rapharehab Duplicate Alt (3 times)
16 http://localhost:3000/about-us/ Physiotherapy at Rapharehab Duplicate Alt (19 times)
17 http://localhost:3000/ourapproach-physiotherapy-etobicoke/ rapharehab Duplicate Alt (3 times)
18 http://localhost:3000/ourapproach-physiotherapy-etobicoke/ Physiotherapy at Rapharehab Duplicate Alt (8 times)
19 http://localhost:3000/our-team-physiotherapy-etobicoke/ rapharehab Duplicate Alt (3 times)
20 http://localhost:3000/gallery-physiotherapy-etobicoke/ rapharehab Duplicate Alt (3 times)
21 http://localhost:3000/covid-19-updates/ rapharehab Duplicate Alt (3 times)
22 http://localhost:3000/etobicoke-treatment-service/ rapharehab Duplicate Alt (3 times)
23 http://localhost:3000/etobicoke-treatment-service/ Osteopathy Clinic In Etobicoke | Rapharehab Duplicate Alt (2 times)
24 http://localhost:3000/etobicoke-treatment-service/ Massage Therapy Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
25 http://localhost:3000/etobicoke-treatment-service/ Acupuncture Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
26 http://localhost:3000/etobicoke-treatment-service/ Chiropodist Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
27 http://localhost:3000/etobicoke-treatment-service/ Chiropractic Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
28 http://localhost:3000/etobicoke-treatment-service/ orthotics in etobicoke | Rapharehab Duplicate Alt (2 times)
29 http://localhost:3000/etobicoke-treatment-service/ foot reflexology clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
30 http://localhost:3000/etobicoke-treatment-service/ custom knee braces clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
31 http://localhost:3000/etobicoke-treatment-service/ laser therapy electrical modalities | Rapharehab Duplicate Alt (2 times)
32 http://localhost:3000/etobicoke-treatment-service/ virtual care physiotherapy clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
33 http://localhost:3000/etobicoke-treatment-service/ naturopathy clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
34 http://localhost:3000/etobicoke-treatment-service/ spinal decompression therapy clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
35 http://localhost:3000/etobicoke-treatment-service/ concussion management clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
36 http://localhost:3000/etobicoke-treatment-service/ Chronic Pain Management Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
37 http://localhost:3000/etobicoke-treatment-service/ prepost operative management clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
38 http://localhost:3000/etobicoke-treatment-service/ ExerciseTherapy Clinic In Etobicoke | Rapharehab Duplicate Alt (2 times)
39 http://localhost:3000/etobicoke-treatment-service/ Workplace Injury Management Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
40 http://localhost:3000/etobicoke-treatment-service/ pelvic floor physiotherapy clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
41 http://localhost:3000/etobicoke-treatment-service/ home care physiotherapy clinic in etobicoke | Rapharehab Duplicate Alt (2 times)
42 http://localhost:3000/etobicoke-treatment-service/ Sports Injury Physiotherapy Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
43 http://localhost:3000/etobicoke-treatment-service/ Gait Assessment | Rapharehab Duplicate Alt (2 times)
44 http://localhost:3000/etobicoke-treatment-service/ kids physiotherapy in etobicoke | Rapharehab Duplicate Alt (2 times)
45 http://localhost:3000/etobicoke-treatment-service/ surgical rehab in etobicoke | Rapharehab Duplicate Alt (2 times)
46 http://localhost:3000/etobicoke-treatment-service/ Physiotherapy Clinic in Etobicoke | Rapharehab Duplicate Alt (2 times)
47 http://localhost:3000/etobicoke-treatment-service/ Fascial Stretch Therapy in Etobicoke | Rapharehab Duplicate Alt (2 times)
48 http://localhost:3000/etobicoke-treatment-service/ cupping therapy in etobicoke | Rapharehab Duplicate Alt (2 times)
49 http://localhost:3000/etobicoke-treatment-service/ Shiatsu Therapy in Etobicoke | Rapharehab Duplicate Alt (2 times)
50 http://localhost:3000/etobicoke-treatment-service/ Deep Tissue Massage in Etobicoke | Rapharehab Duplicate Alt (2 times)
51 http://localhost:3000/etobicoke-treatment-service/ neuro fascial therapy in etobicoke | Rapharehab Duplicate Alt (2 times)
52 http://localhost:3000/etobicoke-treatment-service/ Cranio Sacral Therapy in Etobicoke | Rapharehab Duplicate Alt (2 times)
53 http://localhost:3000/etobicoke-treatment-service/ motor vehicle accident rehabilitation in etobicoke | Rapharehab Duplicate Alt (2 times)
54 http://localhost:3000/etobicoke-treatment-service/ Compression Stockings in Etobicoke | Rapharehab Duplicate Alt (2 times)
55 http://localhost:3000/etobicoke-treatment-service/ Cardiac Rehabilitation in Etobicoke | Rapharehab Duplicate Alt (2 times)
56 http://localhost:3000/etobicoke-treatment-service/ Intramuscular Stimulation IMS in Etobicoke | Rapharehab Duplicate Alt (2 times)
57 http://localhost:3000/etobicoke-treatment-service/ Psychotherapy in Etobicoke | Rapharehab Duplicate Alt (2 times)
58 http://localhost:3000/etobicoke-treatment-service/ Shockwave Therapy in Etobicoke | Rapharehab Duplicate Alt (2 times)
59 http://localhost:3000/etobicoke-treatment-service/ refugee in etobicoke | Rapharehab Duplicate Alt (2 times)
60 http://localhost:3000/area-of-injury/ rapharehab Duplicate Alt (3 times)
61 http://localhost:3000/area-of-injury/ HEAD INJURIES Duplicate Alt (2 times)
62 http://localhost:3000/area-of-injury/ NECK INJURIES Duplicate Alt (2 times)
63 http://localhost:3000/area-of-injury/ SHOULDER INJURIES Duplicate Alt (2 times)
64 http://localhost:3000/area-of-injury/ ELBOW INJURIES Duplicate Alt (2 times)
65 http://localhost:3000/area-of-injury/ WRIST & HAND INJURIES Duplicate Alt (2 times)
66 http://localhost:3000/area-of-injury/ LOW BACK INJURIES Duplicate Alt (2 times)
67 http://localhost:3000/area-of-injury/ HIP INJURIES Duplicate Alt (2 times)
68 http://localhost:3000/area-of-injury/ LEG & KNEE INJURIES Duplicate Alt (2 times)
69 http://localhost:3000/area-of-injury/ ANKLE & FOOT INJURIES Duplicate Alt (2 times)
70 http://localhost:3000/rehabilitation/ rapharehab Duplicate Alt (3 times)
71 http://localhost:3000/accident/ rapharehab Duplicate Alt (3 times)
72 http://localhost:3000/accident/ Minor Injury Duplicate Alt (2 times)
73 http://localhost:3000/accident/ Catastrophic Injury Duplicate Alt (2 times)
74 http://localhost:3000/accident/ Slip and Fall Injury Duplicate Alt (2 times)
75 http://localhost:3000/accident/ Concussion Management Duplicate Alt (2 times)
76 http://localhost:3000/accident/ Psychotherapy Management Duplicate Alt (2 times)
77 http://localhost:3000/accident/ Hydrotherapy Duplicate Alt (2 times)
78 http://localhost:3000/accident/ Chronic Pain Management Duplicate Alt (2 times)
79 http://localhost:3000/blog/ rapharehab Duplicate Alt (3 times)
80 http://localhost:3000/contact/ rapharehab Duplicate Alt (3 times)
81 http://localhost:3000/caregivers/ rapharehab Duplicate Alt (3 times)
82 http://localhost:3000/caregivers/ Physiotherapy at Rapharehab Duplicate Alt (3 times)
83 http://localhost:3000/shortcodes/ rapharehab Duplicate Alt (3 times)
84 http://localhost:3000/shortcodes/ Physiotherapy at Rapharehab Duplicate Alt (6 times)
85 http://localhost:3000/shortcodes/ Why choose nanocare Duplicate Alt (2 times)
86 http://localhost:3000/blog/chronic-pain-treatment-etobicoke/ rapharehab Duplicate Alt (3 times)
87 http://localhost:3000/blog/chronic-pain-treatment-etobicoke/ How Does Rapharehab - Physiotherapy in Etobicoke Treat Chronic Pain Conditions? Duplicate Alt (3 times)
88 http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/ rapharehab Duplicate Alt (3 times)
89 http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/ OSTEOPATHY IN ETOBICOKE Duplicate Alt (2 times)
90 http://localhost:3000/etobicoke-treatment-service/osteopathy-clinic-in-etobicoke/ Osteopathy Clinic In Etobicoke | Rapharehab Duplicate Alt (2 times)
91 http://localhost:3000/area-of-injury/head-injury-physiotherapy-management-in-etobicoke/ rapharehab Duplicate Alt (3 times)
92 http://localhost:3000/area-of-injury/head-injury-physiotherapy-management-in-etobicoke/ HEAD INJURIES Duplicate Alt (5 times)
93 http://localhost:3000/rehabilitation/spinalcord-rehabilitation-clinic-in-etobicoke/ rapharehab Duplicate Alt (3 times)
94 http://localhost:3000/rehabilitation/spinalcord-rehabilitation-clinic-in-etobicoke/ Spinal Cord Injury Rehabilitation Duplicate Alt (2 times)
95 http://localhost:3000/accident/minor-injury-care-in-etobicoke/ rapharehab Duplicate Alt (3 times)
96 http://localhost:3000/accident/minor-injury-care-in-etobicoke/ Minor Injury Duplicate Alt (2 times)
97 http://localhost:3000/our-team-physiotherapy-etobicoke/dhanya-prashant/ rapharehab Duplicate Alt (3 times)

View 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}`);
})();