North Texas Commercial Cleaning Experts | Call (214)-586-0257
Print to PDF
Document IDHWB-TBD
Version2.0.0
Statusâ—Ź APPROVED
Clause7.5

SOP: Website Content and SEO Improvement

Purpose: To provide a standardized process for adding new content and optimizing pages on hwbcleaning.com to improve search engine ranking and user engagement.

Scope: This SOP applies to all new and existing pages, service pages, and blog posts.

Frequency: This process should be followed for every new page created and should be used to review existing key pages at least once per quarter.


Procedure

Follow these steps to ensure all new and updated content is optimized to attract local customers and communicate effectively with search engines.

Step 1: Keyword & Topic Planning

Before writing, identify the main topic and keywords for the page.

  1. Identify the Primary Target: Determine the single most important service or topic for the page.

    • Example: For a new page about cleaning carpets, the primary target is "commercial carpet cleaning."
  2. Identify the Location: For local services, the target location is critical.

    • Example: "Plano, TX"
  3. Combine for Primary Keyword: Combine the service and location.

    • Example: "commercial carpet cleaning in Plano, TX"
  4. Identify Secondary Keywords: Think of related terms or questions.

    • Example: "office carpet cleaning Plano," "business rug cleaning," "stain removal for commercial carpet."

Step 2: Content Creation

  1. Write for Humans: Create detailed, high-quality content (aim for at least 400-500 words) that is genuinely helpful to a potential customer. Fully explain the service, its benefits, and your process.

  2. Use Keywords Naturally: Include your primary and secondary keywords where they make sense. Do not force them in unnaturally. They should appear in headings and paragraphs.

  3. Structure with Headings: Use a clear structure with headings and subheadings (H1, H2, H3).

    • There should only be one H1 heading on the page, which should be the main title and include the primary keyword.
    • Use H2s and H3s for sub-topics.
  4. Add a Call to Action (CTA): End the page with a clear instruction for the reader.

    • Example: "Contact HWB Cleaning today for a free, no-obligation quote on our carpet cleaning services!"

Step 3: On-Page SEO Optimization (SigmaFidelity™ Hardening)

Once the content is written, optimize the page's technical elements.

  1. Canonical URL (MANDATORY): Every page MUST have a canonical link pointing to the primary domain (www.hwbcleaning.com) to prevent authority dilution and ranking fragmentation.

    • Format: <link rel="canonical" href="https://www.hwbcleaning.com/page-slug">
    • Mandate: Never use staging or Azure-specific URLs in production canonical tags.
  2. Social Visibility (OG Tags): Include Open Graph tags in the <head> to ensure high-fidelity previews on professional networks like LinkedIn.

    • Required Tags: og:title, og:description, og:image, og:url.
  3. Page Title (<title>): This is the most important SEO element.

    • Format: Primary Keyword | Brand Name
    • Example: Commercial Carpet Cleaning in Plano, TX | HWB Cleaning
    • Length: Keep it under 60 characters.
  4. Meta Description (<meta name="description">): This is the short text that appears under your title in Google search results.

    • Content: Write an enticing summary of the page. It must include your primary keyword and a call to action.
    • Example: HWB Cleaning offers professional carpet cleaning for offices and businesses in Plano, TX. We handle tough stains and high-traffic areas. Get a free quote today!
    • Length: Keep it under 160 characters.
  5. URL (Slug):

    • Format: Use a short, descriptive URL that contains the primary keyword without the location.
    • Example: www.hwbcleaning.com/commercial-carpet-cleaning
  6. Image Optimization:

    • Filename: Before uploading, name image files with descriptive keywords (e.g., plano-tx-office-carpet-cleaning.jpg).
    • Alt Text: Add descriptive "alt text" to every image. This helps search engines understand the image content.
    • Example Alt Text: Technician from HWB Cleaning steam cleaning a commercial office carpet in Plano, TX.

Step 4: Linking

  1. Internal Linking:
    • From your new page, add at least 1-2 links to other relevant pages on your site (like the /contact or /facility-services page).
    • From an existing, relevant page (like /facility-services), add a link to your new page. This helps search engines discover it and understand its importance.

Step 5: Post-Publishing

  1. Request Indexing: After publishing the page, use the Google Search Console "URL Inspection" tool to submit the new URL. This asks Google to crawl and index your new page faster.

  2. Promote on Google Business Profile: Create a "Post" on your Google Business Profile with a summary of the new service and a link back to the new page on your website. This is a powerful signal for local SEO.


Appendix: Initial SEO Analysis (Example)

The following is a real-world example of a "brutal" SEO analysis conducted on hwbcleaning.com. It identifies the most critical issues and provides a prioritized action plan. This serves as a practical illustration of the concepts discussed in this SOP.


The Ugly: Critical Issues to Fix Immediately

This is the #1 constraint holding you back. If you do nothing else, do this.

  • Your website is invisible to local customers. There is no mention of your service area (e.g., Plano, TX, DFW) in your page title or the content summary. For a local business, this is an SEO death sentence. Google has no idea where you operate, so it will not show your site to people searching for "office cleaning in Plano."
  • Your page title is weak. The title tag () is the most important on-page SEO factor. Yours is just "HWB Cleaning Services LLC.". It tells Google your name, but not what you do or where you do it.</li> <li><strong>You are likely ignoring Google Business Profile.</strong> I cannot see this, but for a local service business, an optimized Google Business Profile (GBP) is more important than your website. It's what appears in the Google Maps listings (the "snack pack"), which is where the majority of local service clicks come from.</li> </ul> <p><strong>Action Plan (Fix these first):</strong></p> <ol> <li><strong>Optimize Your Title Tag:</strong> Change your homepage title to be keyword- and location-focused. Do this now.<ul> <li>From: HWB Cleaning Services LLC.</li> <li>To: Professional Janitorial & Office Cleaning Services in Plano, TX | HWB Cleaning Services LLC</li> </ul> </li> <li><strong>Create and Optimize a Google Business Profile:</strong> Go to google.com/business and either claim or create your profile. Fill out every single section: services, service area, hours, photos, business description. Get reviews from your customers. This is non-negotiable.</li> </ol> <hr /> <h3 id="the-bad-major-issues-to-address-next">The Bad: Major Issues to Address Next</h3> <p>These issues are seriously hindering your ability to compete.</p> <ul> <li><strong>Content is likely too thin.</strong> A single page with "core beliefs" is not enough. Google rewards expertise. You need to prove you are an authority on cleaning services.</li> <li><strong>No clear Call to Action (CTA).</strong> What is the single most important thing you want a visitor to do? "Get a Free Quote"? "Call Us Now"? This should be front and center.</li> <li><strong>Missing Meta Description.</strong> This is the text that appears under your title in Google search results. It's your ad copy. If it's missing, Google will just pull random text from your page, which looks unprofessional and reduces clicks.</li> </ul> <p><strong>Action Plan:</strong></p> <ol> <li><strong>Write a Compelling Meta Description:</strong> Add a meta description to your homepage that is around 155 characters. It should describe your services, include your location, and have a call to action.<ul> <li>Example: "HWB Cleaning offers reliable and affordable janitorial services for offices and commercial properties in Plano, TX. Contact us today for a free, no-obligation quote!"</li> </ul> </li> <li><strong>Build Out Service Pages:</strong> Create separate pages for each of your core services (e.g., "Office Cleaning," "Commercial Janitorial Services," "Post-Construction Cleaning"). Each page should have at least 300-500 words of unique content describing that service.</li> </ol> <hr /> <h3 id="the-good-what-you-can-build-on">The Good: What You Can Build On</h3> <ul> <li>You have a website that is online and functional.</li> <li>Your business name is clear.</li> <li>You mention "janitorial cleaning services," which is a good starting keyword.</li> </ul> <h3 id="conclusion">Conclusion:</h3> <p>Your website is currently a digital business card, but it is not an asset that will generate leads. The primary constraint is its complete lack of local SEO signals.</p> <p>Focus 80% of your effort on optimizing your Google Business Profile and fixing your homepage title tag. These two actions will have the biggest impact on your visibility in local search results.</p> </div> <h2 id="50-revision-history">5.0 Revision History</h2> <table> <thead> <tr> <th style="text-align: left;">Version</th> <th style="text-align: left;">Date</th> <th style="text-align: left;">Author</th> <th style="text-align: left;">Change Description</th> </tr> </thead> <tbody> <tr> <td style="text-align: left;">1.0.0</td> <td style="text-align: left;">04/27/2026</td> <td style="text-align: left;">George (Systems Architect)</td> <td style="text-align: left;">Initial Architecture Baseline.</td> </tr> <tr> <td style="text-align: left;">2.0.0</td> <td style="text-align: left;">09/21/2026</td> <td style="text-align: left;">George (Systems Architect)</td> <td style="text-align: left;">Modernized and upgraded to post-May 1st, 2026 baseline. Standardized under HWB-QMS-1.0 v2.0 (Everyday Words) and approved by Humberto Dominguez, CEO.</td> </tr> </tbody> </table> <div class="sop-card-footer"> <span>© 2026 HWB Cleaning Services LLC</span> <span>Controlled Document | HWB-TBD</span> <span>Page <span class="page-number"></span></span> </div> </div> </div> <!-- Next/Previous Navigation Controls --> <div class="sop-navigation-bar" style="margin-top: 4rem; padding-top: 2rem; border-top: 1px solid #e2e8f0; display: flex; justify-content: space-between; align-items: center;"> <div> <a id="qms-prev-sop" class="qms-nav-btn" style="display: none;"> <svg style="width: 14px; height: 14px; fill: currentColor; transform: rotate(180deg);" viewBox="0 0 24 24"> <path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/> </svg> Previous: <span id="qms-prev-label" style="font-weight: 800; color: #2563eb;">SOP</span> </a> </div> <div> <a href="/manual" class="qms-nav-btn" style="background: #eff6ff; border-color: #dbeafe; color: #2563eb;"> <svg style="width: 14px; height: 14px; fill: currentColor;" viewBox="0 0 24 24"> <path d="M4 15h16v-2H4v2zm0 4h16v-2H4v2zm0-8h16V9H4v2zm0-6v2h16V5H4z"/> </svg> Back to Index </a> </div> <div> <a id="qms-next-sop" class="qms-nav-btn" style="display: none;"> Next: <span id="qms-next-label" style="font-weight: 800; color: #2563eb;">SOP</span> <svg style="width: 14px; height: 14px; fill: currentColor;" viewBox="0 0 24 24"> <path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/> </svg> </a> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', () => { // Find the active link in the sidebar const activeLink = document.querySelector('.dept-sop-link.active'); if (activeLink) { const sopId = activeLink.querySelector('.sop-nav-id').textContent; const sopTitle = activeLink.querySelector('.sop-nav-title').textContent.trim(); const sopUrl = activeLink.href; // 1. Auto-Add to "Recently Viewed" let recentList = JSON.parse(localStorage.getItem('qms_recent_sops') || '[]'); // Remove if already exists to move to top recentList = recentList.filter(item => item.id !== sopId); recentList.unshift({ id: sopId, title: sopTitle, url: sopUrl }); // Cap at 3 items if (recentList.length > 3) recentList.pop(); localStorage.setItem('qms_recent_sops', JSON.stringify(recentList)); // Refresh sidebar queue display if (window.renderQMSQueue) window.renderQMSQueue(); // 2. Initialize Pin Button State const pinBtn = document.getElementById('qms-pin-toggle'); const pinStar = document.getElementById('qms-pin-star'); const pinText = document.getElementById('qms-pin-text'); function updatePinButtonState() { const pinnedList = JSON.parse(localStorage.getItem('qms_pinned_sops') || '[]'); const isPinned = pinnedList.some(item => item.id === sopId); if (isPinned) { pinStar.style.fill = '#eab308'; pinStar.style.stroke = '#ca8a04'; pinText.textContent = 'Pinned in Active Queue'; pinText.style.color = '#ca8a04'; pinBtn.style.background = '#fef8e6'; pinBtn.style.borderColor = '#fde68a'; } else { pinStar.style.fill = 'none'; pinStar.style.stroke = 'currentColor'; pinText.textContent = 'Pin to Active Queue'; pinText.style.color = '#334155'; pinBtn.style.background = '#fff'; pinBtn.style.borderColor = '#cbd5e1'; } } if (pinBtn) { updatePinButtonState(); pinBtn.addEventListener('click', () => { let pinnedList = JSON.parse(localStorage.getItem('qms_pinned_sops') || '[]'); const index = pinnedList.findIndex(item => item.id === sopId); if (index > -1) { pinnedList.splice(index, 1); } else { pinnedList.push({ id: sopId, title: sopTitle, url: sopUrl }); } localStorage.setItem('qms_pinned_sops', JSON.stringify(pinnedList)); updatePinButtonState(); if (window.renderQMSQueue) window.renderQMSQueue(); window.dispatchEvent(new Event('storage')); }); } // Find all links in the sidebar in order const allLinks = Array.from(document.querySelectorAll('.dept-sop-link')); const activeIndex = allLinks.indexOf(activeLink); const prevBtn = document.getElementById('qms-prev-sop'); const nextBtn = document.getElementById('qms-next-sop'); if (activeIndex > 0) { const prevLink = allLinks[activeIndex - 1]; prevBtn.href = prevLink.href; prevBtn.style.display = 'inline-flex'; const prevId = prevLink.querySelector('.sop-nav-id').textContent; document.getElementById('qms-prev-label').textContent = prevId; } if (activeIndex >= 0 && activeIndex < allLinks.length - 1) { const nextLink = allLinks[activeIndex + 1]; nextBtn.href = nextLink.href; nextBtn.style.display = 'inline-flex'; const nextId = nextLink.querySelector('.sop-nav-id').textContent; document.getElementById('qms-next-label').textContent = nextId; } } }); </script> </div> <div class="qms-toc-container"> <span class="toc-label">Document Structure</span> <div class="js-toc"></div> </div> </main> <!-- Dependencies --> <script src="/static/js/mermaid.min.js"></script> <script src="/static/js/highlight.min.js"></script> <script src="/static/js/tocbot.min.js"></script> <script> // Initialize Mermaid mermaid.initialize({ startOnLoad: true, theme: 'neutral', securityLevel: 'loose' }); // Initialize Highlighting document.querySelectorAll('pre code').forEach((el) => { hljs.highlightElement(el); }); // Initialize TocBot tocbot.init({ tocSelector: '.js-toc', contentSelector: '.js-toc-content', headingSelector: 'h2, h3', hasInnerContainers: true, }); // Accordion Toggle document.querySelectorAll('.accordion-trigger').forEach(trigger => { trigger.addEventListener('click', () => { const item = trigger.closest('.accordion-item'); const content = item.querySelector('.accordion-content'); const chevron = trigger.querySelector('.chevron-icon'); const isOpen = item.classList.contains('open'); if (isOpen) { content.style.maxHeight = '0px'; item.classList.remove('open'); chevron.style.transform = 'rotate(0deg)'; } else { // Temporarily set height to scrollHeight for smooth transition content.style.maxHeight = content.scrollHeight + 'px'; item.classList.add('open'); chevron.style.transform = 'rotate(180deg)'; // After transition completes, change to auto/none to prevent scaling issues if content changes setTimeout(() => { if (item.classList.contains('open')) { content.style.maxHeight = 'none'; } }, 300); } }); }); // Set initial heights on page load for open items document.querySelectorAll('.accordion-item.open .accordion-content').forEach(content => { content.style.maxHeight = 'none'; }); // Sidebar Search Filtering const searchInput = document.getElementById('qms-sidebar-search'); if (searchInput) { searchInput.addEventListener('input', (e) => { const query = e.target.value.toLowerCase().trim(); document.querySelectorAll('.accordion-item').forEach(item => { const sopLinks = item.querySelectorAll('.dept-sop-link'); let hasMatch = false; sopLinks.forEach(link => { const title = link.getAttribute('data-title') || ''; const id = link.getAttribute('data-id') || ''; if (title.includes(query) || id.includes(query)) { link.style.display = 'block'; hasMatch = true; } else { link.style.display = 'none'; } }); const deptTrigger = item.querySelector('.accordion-trigger'); const deptName = deptTrigger.textContent.toLowerCase(); // If department name matches, show all links in that department if (deptName.includes(query)) { sopLinks.forEach(link => link.style.display = 'block'); hasMatch = true; } const content = item.querySelector('.accordion-content'); const chevron = item.querySelector('.chevron-icon'); if (query.length > 0) { if (hasMatch) { item.style.display = 'block'; item.classList.add('open'); content.style.maxHeight = 'none'; chevron.style.transform = 'rotate(180deg)'; } else { item.style.display = 'none'; } } else { // Restore original state item.style.display = 'block'; const hasActiveLink = item.querySelector('.dept-sop-link.active') !== null; if (hasActiveLink) { item.classList.add('open'); content.style.maxHeight = 'none'; chevron.style.transform = 'rotate(180deg)'; } else { item.classList.remove('open'); content.style.maxHeight = '0px'; chevron.style.transform = 'rotate(0deg)'; } } }); }); } // Render Pinned and Recent lists (Option A & B Integration) window.renderQMSQueue = function() { const pinnedList = JSON.parse(localStorage.getItem('qms_pinned_sops') || '[]'); const recentList = JSON.parse(localStorage.getItem('qms_recent_sops') || '[]'); const pinnedContainer = document.getElementById('qms-pinned-section'); const pinnedListDiv = document.getElementById('qms-pinned-list'); const recentContainer = document.getElementById('qms-recent-section'); const recentListDiv = document.getElementById('qms-recent-list'); if (!pinnedContainer || !pinnedListDiv || !recentContainer || !recentListDiv) return; // Pinned Render if (pinnedList.length > 0) { pinnedContainer.style.display = 'block'; pinnedListDiv.innerHTML = pinnedList.map(sop => ` <div style="display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; width: 100%;"> <a href="${sop.url}" class="qms-nav-link" style="padding: 0.25rem 0; font-size: 0.75rem; border: none; background: none; text-decoration: none; color: #fff; flex-grow: 1; display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; line-height: 1.2;"> <svg style="width: 10px; height: 10px; fill: #eab308; flex-shrink: 0;" viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> <span style="font-weight: 800; color: #60a5fa; margin-right: 0.2rem;">${sop.id}</span> <span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; font-weight: 500; opacity: 0.85;">${sop.title}</span> </a> <button onclick="window.removeQMSpinned('${sop.id}')" aria-label="Remove pinned SOP" title="Remove pinned SOP" style="background: none; border: none; padding: 0.2rem; cursor: pointer; color: rgba(255,255,255,0.4); display: inline-flex; align-items: center; justify-content: center; transition: color 0.2s;" onmouseover="this.style.color='#f87171'" onmouseout="this.style.color='rgba(255,255,255,0.4)'"> <svg style="width: 10px; height: 10px; fill: currentColor;" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> </button> </div> `).join(''); } else { pinnedContainer.style.display = 'none'; pinnedListDiv.innerHTML = ''; } // Recent Render const filteredRecent = recentList.filter(sop => !pinnedList.some(p => p.id === sop.id)); if (filteredRecent.length > 0) { recentContainer.style.display = 'block'; recentListDiv.innerHTML = filteredRecent.map(sop => ` <a href="${sop.url}" class="qms-nav-link" style="padding: 0.25rem 0; font-size: 0.75rem; border: none; background: none; text-decoration: none; color: rgba(255,255,255,0.65); display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; line-height: 1.2;"> <svg style="width: 10px; height: 10px; fill: rgba(255,255,255,0.4); flex-shrink: 0;" viewBox="0 0 24 24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg> <span style="font-weight: 700; color: rgba(96,165,250,0.7); margin-right: 0.2rem;">${sop.id}</span> <span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; font-weight: 500;">${sop.title}</span> </a> `).join(''); } else { recentContainer.style.display = 'none'; recentListDiv.innerHTML = ''; } }; window.removeQMSpinned = function(sopId) { let pinnedList = JSON.parse(localStorage.getItem('qms_pinned_sops') || '[]'); pinnedList = pinnedList.filter(sop => sop.id !== sopId); localStorage.setItem('qms_pinned_sops', JSON.stringify(pinnedList)); window.renderQMSQueue(); window.dispatchEvent(new Event('storage')); }; // Initial load window.renderQMSQueue(); // Listen to storage events to sync active queues in real time across pages window.addEventListener('storage', () => { window.renderQMSQueue(); }); // Sidebar Drag-to-Resize Logic const sidebar = document.querySelector('.qms-sidebar'); const resizer = document.getElementById('qms-sidebar-resizer'); const mainContent = document.querySelector('.qms-main'); if (sidebar && resizer && mainContent) { // Retrieve persisted width on initial load const savedWidth = localStorage.getItem('qms_sidebar_width'); if (savedWidth) { document.documentElement.style.setProperty('--qms-sidebar-width', savedWidth + 'px'); } let isResizing = false; resizer.addEventListener('mousedown', (e) => { isResizing = true; resizer.classList.add('resizing'); document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; // Prevent text selection on drag e.preventDefault(); }); window.addEventListener('mousemove', (e) => { if (!isResizing) return; // Set boundary constraints let newWidth = e.clientX; if (newWidth < 280) newWidth = 280; if (newWidth > 500) newWidth = 500; // Update dynamic CSS variable document.documentElement.style.setProperty('--qms-sidebar-width', newWidth + 'px'); // Persist preferred size localStorage.setItem('qms_sidebar_width', newWidth); }); window.addEventListener('mouseup', () => { if (isResizing) { isResizing = false; resizer.classList.remove('resizing'); document.body.style.cursor = 'default'; document.body.style.userSelect = 'auto'; } }); } </script> </body> </html>