<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zehlm Web Development LLC</title>
    <description>The latest articles on DEV Community by Zehlm Web Development LLC (@zehlm).</description>
    <link>https://dev.to/zehlm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3978402%2Fe679e540-2d1d-429a-8e14-15c9c6f08d3b.jpg</url>
      <title>DEV Community: Zehlm Web Development LLC</title>
      <link>https://dev.to/zehlm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zehlm"/>
    <language>en</language>
    <item>
      <title>The Technical Guide to Google Business Profile Setup for Morganton, NC Business Owners</title>
      <dc:creator>Zehlm Web Development LLC</dc:creator>
      <pubDate>Sun, 14 Jun 2026 23:25:43 +0000</pubDate>
      <link>https://dev.to/zehlm/the-technical-guide-to-google-business-profile-setup-for-morganton-nc-business-owners-8p</link>
      <guid>https://dev.to/zehlm/the-technical-guide-to-google-business-profile-setup-for-morganton-nc-business-owners-8p</guid>
      <description>&lt;p&gt;Most "how to set up your Google Business Profile" guides amount to: claim it, fill in the blanks, add some photos, done. That's the surface. Underneath, Google is running a verification process that's gotten significantly stricter, cross-referencing your business data against everything else it can find about you on the web, and slotting your listing into a fixed taxonomy that determines which searches you're even eligible to show up for.&lt;/p&gt;

&lt;p&gt;If you're a business owner in Morganton or anywhere in Burke County, here's what's actually happening when you set up a profile — and where the real mistakes get made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification: It's Not Just a Formality Anymore
&lt;/h2&gt;

&lt;p&gt;Verification is Google's process for confirming you're a real business at a real location, run by someone authorized to manage it. For years this meant a postcard in the mail with a code. That's changed.&lt;/p&gt;

&lt;p&gt;Video verification has become the dominant method in 2026, used in roughly eight out of ten cases according to local SEO professionals tracking the rollout. The video verification process checks three things in a single recording: that it confirms the listed address, shows real operations at that location, and demonstrates management access.&lt;/p&gt;

&lt;p&gt;A few technical details worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verification methods are automatically determined by Google based on your business type, public information, region, and hours — you can't request a specific method&lt;/li&gt;
&lt;li&gt;If video is offered, record one continuous take on a mobile device — exterior signage and street context first, then interior, then something that demonstrates you actually operate there (inventory, equipment, staff)&lt;/li&gt;
&lt;li&gt;If you edit your business name, address, or category while a verification code is pending, that code becomes invalid — finish verification before making any other profile changes&lt;/li&gt;
&lt;li&gt;Any future edit to name, address, or category can trigger re-verification, so get these fields right the first time rather than treating them as easy to tweak later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For service-area businesses especially — which covers a lot of Burke County's contractors, electricians, HVAC techs, and similar trades — video verification gets extra scrutiny because there's often no public storefront to point a camera at. Google still requires a real address behind the listing even when it's hidden from public view, and the video needs to demonstrate that the address is a legitimate operating location, not just a residence with no connection to the business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Category Selection: You're Choosing From a Fixed List
&lt;/h2&gt;

&lt;p&gt;Google maintains its own taxonomy of business categories — you don't get to type in whatever you want. This matters more than most business owners realize, because &lt;strong&gt;your primary category determines which features your profile is eligible for&lt;/strong&gt; — things like a Services tab, booking integration, menu support, or service-area display.&lt;/p&gt;

&lt;p&gt;The mistake we see most often: businesses pick a broad category ("Marketing Agency," "Contractor") because it feels safer or more impressive, when a more specific category in Google's list ("Website Designer," "Fence Contractor," "Roofing Contractor") is both more accurate and more likely to surface for the exact searches people are running.&lt;/p&gt;

&lt;p&gt;Secondary categories add reach, but the primary category is the one doing the heavy lifting for relevance — which is the first of three things Google's local algorithm evaluates.&lt;/p&gt;

&lt;h2&gt;
  
  
  NAP Data and the Entity Graph
&lt;/h2&gt;

&lt;p&gt;Here's the part that connects your Google Business Profile to everything else happening with your website and citations.&lt;/p&gt;

&lt;p&gt;Google doesn't treat your GBP as an isolated record. It's trying to build a confident picture of your business as an &lt;em&gt;entity&lt;/em&gt; — and it does that by cross-referencing your business Name, Address, and Phone number (NAP) everywhere it appears: directory listings, chamber of commerce pages, your own website.&lt;/p&gt;

&lt;p&gt;Two technical pieces that feed this directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LocalBusiness schema on your website.&lt;/strong&gt; If your site has JSON-LD structured data marking it up as a &lt;code&gt;LocalBusiness&lt;/code&gt; (or a more specific subtype), the name/address/phone in that schema needs to match your GBP exactly — same formatting, same suite number, same phone format. A &lt;code&gt;sameAs&lt;/code&gt; property linking to your GBP URL and social profiles helps Google connect the dots between your website and your profile as the same entity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Citation consistency.&lt;/strong&gt; Every directory listing — Chamber of Commerce, BBB, industry-specific directories — is another data point Google checks your NAP against. Inconsistencies don't get your listing rejected, but they lower Google's &lt;em&gt;confidence&lt;/em&gt; in the entity, which shows up as weaker local pack performance even when everything else looks fine.&lt;/p&gt;

&lt;p&gt;If you've ever wondered why two businesses with seemingly similar profiles perform differently in the map results, citation consistency is one of the most common invisible differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Area vs. Storefront
&lt;/h2&gt;

&lt;p&gt;If customers come to your location, set up a storefront listing with your real address public. If you go to customers — most home services fall here — set up a service-area business (SAB) profile instead.&lt;/p&gt;

&lt;p&gt;Technical points that matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An SAB still requires a real address on file with Google, even though it's hidden from public view — this is what verification is checking&lt;/li&gt;
&lt;li&gt;You define service areas by city, zip code, or county — Google's own guidance is to avoid setting areas beyond where you can realistically provide same-day service, since overly broad service areas are a common red flag in the verification and spam-detection process&lt;/li&gt;
&lt;li&gt;For Burke County businesses, this usually means Morganton plus the surrounding towns you actually serve — not "all of Western North Carolina" unless that's genuinely true&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services and Products: Structured Data That Surfaces in Search
&lt;/h2&gt;

&lt;p&gt;The Services section isn't just a list — each entry can include a name, description, and price or price range. This is structured data that Google can pull directly into search results when someone searches for that specific service.&lt;/p&gt;

&lt;p&gt;A generic "Web Design" entry with no description does almost nothing. "Custom Website Design — starting at $X, includes mobile-responsive design and basic SEO setup" gives Google something concrete to match against a specific search, and gives the searcher a reason to click through to you specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Pillars: Relevance, Distance, Prominence
&lt;/h2&gt;

&lt;p&gt;Google's local ranking algorithm comes down to three factors, and it's worth knowing which setup decisions affect which pillar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relevance&lt;/strong&gt; — how well your profile matches what someone searched for. Category selection, service descriptions, business description, and regular posts all feed this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distance&lt;/strong&gt; — how close you are to the searcher (or, for service-area businesses, how well your defined area matches their location). This is largely fixed by your actual location and service area settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prominence&lt;/strong&gt; — your overall presence and reputation: review count and quality, citation consistency, and the authority of your website (backlinks, content). This is the slowest to build and the hardest to fake — which is exactly why it's the most valuable signal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A perfectly configured profile with zero reviews and no citations will still underperform a decent profile backed by real prominence signals. Setup gets you eligible to compete; prominence is what you compete with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Your Performance Data
&lt;/h2&gt;

&lt;p&gt;Once verified and active, your profile's Performance section (formerly "Insights") gives you real data: how people found you (direct search for your business name vs. discovery search for what you do vs. branded searches), what actions they took (website visits, calls, direction requests, messages), and how your photos compare to similar businesses.&lt;/p&gt;

&lt;p&gt;This data is the feedback loop. If discovery searches are low relative to direct searches, your category or service descriptions likely aren't matching the searches people are actually running. If photo views lag behind similar businesses, that's a concrete, fixable gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Duplicate Listings: The Hidden Technical Problem
&lt;/h2&gt;

&lt;p&gt;Duplicate listings — often created accidentally when a business changes hands, rebrands, or gets listed by a data provider in addition to being self-claimed — split your reviews and signals across two profiles instead of consolidating them into one. From Google's side, it also muddies the entity graph: two listings claiming to be the same business at the same address is itself a signal that gets scrutinized.&lt;/p&gt;

&lt;p&gt;If you suspect a duplicate exists, search for your business on Google Maps under slightly different name variations or old addresses. Duplicates can be flagged via "Suggest an edit" → "This place doesn't exist" on the listing that shouldn't remain.&lt;/p&gt;




&lt;p&gt;Setting this up correctly the first time avoids re-verification headaches down the line, and gets your profile contributing to relevance and prominence from day one instead of fighting an uphill battle against its own data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this all sounds like more than you bargained for when someone told you to "just claim your Google listing" — that's because it is. This is the kind of setup work we handle as part of local SEO for clients at &lt;a href="https://www.zehlm.com/morganton-nc" rel="noopener noreferrer"&gt;Zehlm Web Development&lt;/a&gt;, based right here in Morganton, NC.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>localseo</category>
      <category>googlebusiness</category>
      <category>morganton</category>
      <category>smallbusiness</category>
    </item>
    <item>
      <title>We Got Blacklisted Because of a Banking Trojan We Didn't Even Have</title>
      <dc:creator>Zehlm Web Development LLC</dc:creator>
      <pubDate>Sun, 14 Jun 2026 22:58:23 +0000</pubDate>
      <link>https://dev.to/zehlm/our-domain-mail-was-blacklisted-because-of-a-banking-trojan-we-didnt-even-have-5be</link>
      <guid>https://dev.to/zehlm/our-domain-mail-was-blacklisted-because-of-a-banking-trojan-we-didnt-even-have-5be</guid>
      <description>&lt;p&gt;One morning, email on our primary domain just... stopped working.&lt;/p&gt;

&lt;p&gt;No bounce messages. No error a normal user would ever see. Outgoing mail vanished into nothing, and nothing was coming in either. For a small agency where half of new business arrives by email, that's not a minor inconvenience — that's the front door nailed shut.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opening the Ticket
&lt;/h2&gt;

&lt;p&gt;First instinct was to check the obvious stuff: DNS records, mail server config, SPF/DKIM — all fine. So we opened a support ticket with our hosting provider and waited.&lt;/p&gt;

&lt;p&gt;The answer that came back wasn't what we expected: our server's IP address had landed on the &lt;strong&gt;Spamhaus blacklist&lt;/strong&gt; — one of the most widely used spam-reputation lists in the world. Once an IP is on it, a huge percentage of mail servers worldwide will silently drop or reject anything coming from that address. That's why we weren't seeing bounces — recipient servers weren't even bothering to tell us.&lt;/p&gt;

&lt;p&gt;Here's the part that stung: it wasn't anything we did. According to the hosting provider, another account on the same shared server had a banking trojan running on it, generating exactly the kind of malicious outbound traffic that gets an IP flagged. We were sharing an IP address with a compromised neighbor, and Spamhaus doesn't care whose account is actually infected — it blacklists the IP.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem: Shared Infrastructure, Shared Reputation
&lt;/h2&gt;

&lt;p&gt;This is the part that's actually worth internalizing if you're running anything important on shared hosting: &lt;strong&gt;your domain's email deliverability is tied to the security hygiene of every other account on that server&lt;/strong&gt; — accounts you have no visibility into and no control over.&lt;/p&gt;

&lt;p&gt;You can have a spotless setup. Strong passwords, clean code, no vulnerable plugins. None of that matters if the account two slots over from yours gets compromised and starts spraying spam or malware traffic from the same IP. You inherit their blacklist.&lt;/p&gt;

&lt;p&gt;For most small businesses, this risk is invisible until the day it isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 48-Hour Move
&lt;/h2&gt;

&lt;p&gt;Once we understood the actual cause, staying on that shared IP wasn't really an option — even after cleanup, a blacklisted IP can take time to get delisted, and there was zero guarantee another account on the same server wouldn't cause the same problem again next month.&lt;/p&gt;

&lt;p&gt;So we moved fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spun up a dedicated VM on Google Cloud Platform — our own IP, our own environment, no neighbors&lt;/li&gt;
&lt;li&gt;Transferred the domain to Cloudflare's registrar for better control over DNS and security settings&lt;/li&gt;
&lt;li&gt;Set up mail through Zoho Mail with a PHPMailer relay, so outbound mail from the server goes through a reputation-managed provider instead of relying on the VM's raw IP reputation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point matters as much as the migration itself — even on a dedicated server, we didn't want our deliverability resting entirely on one IP's reputation again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Locking It Down
&lt;/h2&gt;

&lt;p&gt;Once we were on infrastructure we fully controlled, we hardened it properly — things that aren't possible (or aren't your job) on shared hosting:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fail2ban with guaranteed uptime.&lt;/strong&gt; Fail2ban watches logs and bans IPs showing brute-force or scanning behavior, but if the service itself crashes, you're unprotected. We added a systemd override so it restarts automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# /etc/systemd/system/fail2ban.service.d/override.conf
&lt;/span&gt;&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Persistent firewall blocks.&lt;/strong&gt; Known-bad IPs get dropped at the firewall level and the rule survives reboots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;iptables &lt;span class="nt"&gt;-A&lt;/span&gt; INPUT &lt;span class="nt"&gt;-s&lt;/span&gt; &amp;lt;malicious-ip&amp;gt; &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;span class="nb"&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;reCAPTCHA Enterprise on every form.&lt;/strong&gt; Not directly related to the blacklist, but part of the same "stop being an easy target" push — bot traffic and automated form abuse are exactly the kind of noise that can snowball into the next incident.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We'd Tell Anyone on Shared Hosting
&lt;/h2&gt;

&lt;p&gt;You don't need to migrate to a VM tomorrow to take one useful thing from this. Periodically check whether your mail server's IP is on a blacklist — it takes thirty seconds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://check.spamhaus.org" rel="noopener noreferrer"&gt;check.spamhaus.org&lt;/a&gt; — Spamhaus's own lookup&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mxtoolbox.com/blacklists.aspx" rel="noopener noreferrer"&gt;mxtoolbox.com/blacklists.aspx&lt;/a&gt; — checks dozens of blacklists at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're on shared hosting and you ever see mail mysteriously stop arriving with no errors, this is the first thing to check — and it's worth knowing before it happens, not during a support ticket at 9am with clients trying to reach you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;These are the same lessons we apply to every infrastructure decision at &lt;a href="https://www.zehlm.com" rel="noopener noreferrer"&gt;Zehlm Web Development&lt;/a&gt; — a custom web design and digital marketing agency based in Morganton, NC.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hosting</category>
      <category>security</category>
      <category>devops</category>
      <category>email</category>
    </item>
    <item>
      <title>5 PageSpeed Optimizations That Took My Client Sites from 56 to 92 on Mobile</title>
      <dc:creator>Zehlm Web Development LLC</dc:creator>
      <pubDate>Wed, 10 Jun 2026 22:09:57 +0000</pubDate>
      <link>https://dev.to/zehlm/5-pagespeed-optimizations-that-took-my-client-sites-from-56-to-92-on-mobile-4ea5</link>
      <guid>https://dev.to/zehlm/5-pagespeed-optimizations-that-took-my-client-sites-from-56-to-92-on-mobile-4ea5</guid>
      <description>&lt;p&gt;If you're building sites for small businesses, PageSpeed scores matter more than ever. Google uses Core Web Vitals as a ranking factor, and a 56 on mobile is quietly killing your client's SEO. Here's exactly what moved the needle for us.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. &lt;strong&gt;&lt;em&gt;Fix Your LCP Image First&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The single biggest win on every project. Largest Contentful Paint is almost always the hero image. Two things that made an immediate difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert to WebP. We target ~45KB desktop, ~22–28KB mobile using a &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element with separate &lt;code&gt;srcset&lt;/code&gt; values.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;fetchpriority="high"&lt;/code&gt; to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag. This tells the browser to prioritize it above everything else.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero-mobile.webp"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 768px)"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero-desktop.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero-desktop.jpg"&lt;/span&gt; &lt;span class="na"&gt;fetchpriority=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Hero image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't lazy-load your LCP image. Ever.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;strong&gt;&lt;em&gt;Load Your Critical CSS Synchronously&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This one surprises people. We had async preload on our main stylesheet to speed up initial load — it was actually causing CLS (Cumulative Layout Shift) because the page rendered before styles applied.&lt;/p&gt;

&lt;p&gt;The fix: load &lt;code&gt;site.css&lt;/code&gt; as a standard synchronous stylesheet. Yes, it blocks render slightly, but it eliminates the layout shift entirely and the CLS score goes to zero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Do this --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/css/site.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Not this for critical CSS --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/css/site.css"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reserve async preload for non-critical CSS only.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;strong&gt;&lt;em&gt;Defer Third-Party Scripts Aggressively&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Google Analytics was costing us 0.3–0.5s on every page. We moved GA4 behind Cloudflare Zaraz with a 2-second blocking trigger — it fires after the page is interactive, not during load. Scores jumped immediately.&lt;/p&gt;

&lt;p&gt;For anything you can't defer through a tag manager, use the &lt;code&gt;defer&lt;/code&gt; attribute at minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"analytics.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it doesn't affect the visible page on load, it shouldn't block render. No exceptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;strong&gt;&lt;em&gt;Preload Your Custom Fonts&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you're self-hosting fonts (and you should be — Google Fonts adds a render-blocking request), preload them in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; with &lt;code&gt;font-display: swap&lt;/code&gt; in your CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/fonts/opensans.woff2"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Open Sans'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('/fonts/opensans.woff2')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff2'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;font-display: swap&lt;/code&gt; ensures text renders in a fallback font immediately while the custom font loads, eliminating invisible text flashes that tank your FCP score.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;strong&gt;&lt;em&gt;Enable OPcache and HTTP/2 on Your Server&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Front-end optimizations only go so far. On the server side, two quick wins that most shared hosting setups miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OPcache&lt;/strong&gt; — caches compiled PHP bytecode in memory. On a PHP 8.x stack this alone can cut TTFB by 40–60ms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt; — enables multiplexing so the browser loads multiple assets in parallel over a single connection instead of queuing them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Apache, confirm both are active:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-i&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;opcache.enable
apache2ctl &lt;span class="nt"&gt;-M&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;http2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If OPcache isn't enabled, add this to your &lt;code&gt;php.ini&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;opcache.enable&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;opcache.memory_consumption&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;128&lt;/span&gt;
&lt;span class="py"&gt;opcache.max_accelerated_files&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Combining all five on a roofing company site: 56 → 92 mobile, 91 → 99 desktop. Core Web Vitals went all green within two weeks of Google recrawling.&lt;/p&gt;

&lt;p&gt;These aren't tricks — they're fundamentals that get skipped when you're moving fast. Slow down on these five and your clients will notice the difference in rankings.&lt;/p&gt;




&lt;p&gt;These are the same techniques we use on every build at &lt;a href="https://www.zehlm.com/morganton-nc" rel="noopener noreferrer"&gt;Zehlm Web Development&lt;/a&gt; — a custom web design and SEO agency based in Morganton, NC.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>css</category>
      <category>pagespeed</category>
    </item>
  </channel>
</rss>
