DEV Community

Deniz Egemen
Deniz Egemen

Posted on

Technical SEO for Developers: From 0 to 10M Impressions

Technical SEO for Developers: From 0 to 10M Impressions

6 years, 200+ sites, real performance data

TL;DR

  • Core Web Vitals = SEO rankings in 2024
  • Schema markup boosts click-through rates by 30%+
  • Automated sitemaps and meta generation saves hours
  • Performance optimization directly impacts conversion

Core Web Vitals: The Technical Foundation

Largest Contentful Paint (LCP) < 2.5s

// Next.js optimization
import Image from 'next/image';

const HeroSection = () => (
  <Image
    src="/hero.webp"
    alt="Hero image"
    width={1200}
    height={600}
    priority // Critical for LCP
    sizes="(max-width: 768px) 100vw, 1200px"
  />
);

// Preload critical resources
<link rel="preload" href="/critical-font.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/hero.webp" as="image" />
Enter fullscreen mode Exit fullscreen mode

First Input Delay (FID) < 100ms

// Code splitting for better FID
const LazyModal = lazy(() => import('./Modal'));

// Web Workers for heavy tasks
const worker = new Worker('/calculator-worker.js');
worker.postMessage({operation: 'calculate', data: bigDataSet});
Enter fullscreen mode Exit fullscreen mode

Cumulative Layout Shift (CLS) < 0.1

/* Prevent layout shifts */
.image-placeholder {
  aspect-ratio: 16 / 9;
  background: #f0f0f0;
}

@font-face {
  font-family: 'CustomFont';
  src: url('/font.woff2') format('woff2');
  font-display: swap; /* Prevents invisible text */
}
Enter fullscreen mode Exit fullscreen mode

Schema Markup That Actually Works

Product Schema for E-commerce

const ProductSchema = ({ product }) => {
  const schema = {
    "@context": "https://schema.org/",
    "@type": "Product",
    "name": product.name,
    "description": product.description,
    "image": product.images,
    "brand": {"@type": "Brand", "name": product.brand},
    "offers": {
      "@type": "Offer",
      "price": product.price,
      "priceCurrency": "USD",
      "availability": "https://schema.org/InStock"
    },
    "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": product.rating,
      "reviewCount": product.reviews
    }
  };

  return (
    <script 
      type="application/ld+json"
      dangerouslySetInnerHTML={{__html: JSON.stringify(schema)}}
    />
  );
};
Enter fullscreen mode Exit fullscreen mode

Article Schema for Better SERP

const ArticleSchema = ({ article }) => ({
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": article.title,
  "image": article.featuredImage,
  "datePublished": article.publishDate,
  "dateModified": article.modifiedDate,
  "author": {
    "@type": "Person", 
    "name": article.author
  },
  "publisher": {
    "@type": "Organization",
    "name": "DEOK YAZILIM",
    "logo": "https://deokyazilim.com/logo.png"
  }
});
Enter fullscreen mode Exit fullscreen mode

Automated Sitemap Generation

Dynamic Next.js Sitemap

// pages/sitemap.xml.js
export async function getServerSideProps({ res }) {
  const baseUrl = 'https://yoursite.com';
  const posts = await getAllBlogPosts();
  const products = await getAllProducts();

  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <url>
        <loc>${baseUrl}</loc>
        <lastmod>${new Date().toISOString()}</lastmod>
        <changefreq>daily</changefreq>
        <priority>1.0</priority>
      </url>

      ${posts.map(post => `
        <url>
          <loc>${baseUrl}/blog/${post.slug}</loc>
          <lastmod>${post.updatedAt}</lastmod>
          <changefreq>weekly</changefreq>
          <priority>0.8</priority>
        </url>
      `).join('')}

      ${products.map(product => `
        <url>
          <loc>${baseUrl}/products/${product.slug}</loc>
          <lastmod>${product.updatedAt}</lastmod>
          <changefreq>weekly</changefreq>
          <priority>0.9</priority>
        </url>
      `).join('')}
    </urlset>`;

  res.setHeader('Content-Type', 'text/xml');
  res.write(sitemap);
  res.end();
  return { props: {} };
}
Enter fullscreen mode Exit fullscreen mode

Google Analytics 4 Implementation

Enhanced E-commerce Tracking

// lib/gtag.js
export const trackPurchase = (transactionId, items, value) => {
  gtag('event', 'purchase', {
    transaction_id: transactionId,
    value: value,
    currency: 'USD',
    items: items.map(item => ({
      item_id: item.id,
      item_name: item.name,
      category: item.category,
      quantity: item.quantity,
      price: item.price
    }))
  });
};

export const trackFormSubmission = (formType) => {
  gtag('event', 'generate_lead', {
    form_type: formType,
    value: 50, // Lead value
    currency: 'USD'
  });
};
Enter fullscreen mode Exit fullscreen mode

React Analytics Hook

import { useRouter } from 'next/router';
import { useEffect } from 'react';

export const useAnalytics = () => {
  const router = useRouter();

  useEffect(() => {
    const handleRouteChange = (url) => {
      gtag('config', GA_TRACKING_ID, {
        page_location: url,
        page_title: document.title
      });
    };

    router.events.on('routeChangeComplete', handleRouteChange);
    return () => router.events.off('routeChangeComplete', handleRouteChange);
  }, [router.events]);

  return {
    trackEvent: (eventName, parameters) => gtag('event', eventName, parameters),
    trackConversion: (conversionName, value) => gtag('event', 'conversion', {
      send_to: `${GA_TRACKING_ID}/${conversionName}`,
      value: value
    })
  };
};
Enter fullscreen mode Exit fullscreen mode

SEO Component Library

Smart Meta Component

// components/SEO.js
import Head from 'next/head';

const SEO = ({ 
  title, 
  description, 
  canonical, 
  ogImage,
  noindex = false 
}) => {
  const fullTitle = title ? `${title} | DEOK YAZILIM` : 'DEOK YAZILIM';
  const truncDesc = description?.slice(0, 160);

  return (
    <Head>
      <title>{fullTitle}</title>
      <meta name="description" content={truncDesc} />
      <link rel="canonical" href={canonical} />

      {noindex && <meta name="robots" content="noindex,nofollow" />}

      {/* Open Graph */}
      <meta property="og:title" content={fullTitle} />
      <meta property="og:description" content={truncDesc} />
      <meta property="og:image" content={ogImage} />
      <meta property="og:url" content={canonical} />

      {/* Twitter Card */}
      <meta name="twitter:card" content="summary_large_image" />
      <meta name="twitter:title" content={fullTitle} />
      <meta name="twitter:description" content={truncDesc} />
      <meta name="twitter:image" content={ogImage} />
    </Head>
  );
};
Enter fullscreen mode Exit fullscreen mode

Automated Internal Linking

// lib/internalLinking.js
export const addInternalLinks = (content, linkMap) => {
  let linkedContent = content;

  Object.entries(linkMap).forEach(([keyword, url]) => {
    const regex = new RegExp(`\\b${keyword}\\b`, 'i');
    if (regex.test(linkedContent) && !linkedContent.includes(`href="${url}"`)) {
      linkedContent = linkedContent.replace(
        regex, 
        `<a href="${url}" title="${keyword}">${keyword}</a>`
      );
    }
  });

  return linkedContent;
};

// Usage
const linkMap = {
  'React Native': '/hizmetlerimiz/mobil-uygulama',
  'ERP sistemi': '/hizmetlerimiz/erp',
  'SEO': '/hizmetlerimiz/seo-digital-marketing'
};

const linkedContent = addInternalLinks(blogContent, linkMap);
Enter fullscreen mode Exit fullscreen mode

Performance Optimization

Image Optimization Pipeline

// next.config.js
module.exports = {
  images: {
    domains: ['cdn.deokyazilim.com'],
    formats: ['image/webp', 'image/avif'],
    minimumCacheTTL: 31536000, // 1 year
  },

  // Gzip compression
  compress: true,

  // Bundle optimization
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback.fs = false;
    }
    return config;
  },
};
Enter fullscreen mode Exit fullscreen mode

Critical CSS Extraction

// lib/criticalCSS.js
import { PurgeCSS } from 'purgecss';

export const extractCriticalCSS = async (html, cssFiles) => {
  const result = await new PurgeCSS().purge({
    content: [{ raw: html, extension: 'html' }],
    css: cssFiles,
    whitelist: ['html', 'body']
  });

  return result[0].css;
};

// Inline critical CSS
const CriticalCSS = ({ css }) => (
  <style dangerouslySetInnerHTML={{__html: css}} />
);
Enter fullscreen mode Exit fullscreen mode

Local SEO Implementation

Google My Business Schema

const LocalBusinessSchema = ({ business }) => ({
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "DEOK YAZILIM",
  "image": "https://deokyazilim.com/logo.png",
  "telephone": "+90-XXX-XXX-XXXX",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "İstanbul",
    "addressCountry": "TR"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": "41.0082",
    "longitude": "28.9784"
  },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "opens": "09:00",
    "closes": "18:00"
  }]
});
Enter fullscreen mode Exit fullscreen mode

Content Optimization

SEO Content Analyzer

// lib/contentAnalyzer.js
export const analyzeContent = (content) => {
  const words = content.split(/\s+/).length;
  const sentences = content.split(/[.!?]+/).length;
  const readability = calculateReadability(content);
  const keywordDensity = analyzeKeywords(content);

  return {
    wordCount: words,
    readabilityScore: readability,
    keywordDensity,
    recommendations: generateSEORecommendations(words, readability, keywordDensity)
  };
};

const generateSEORecommendations = (words, readability, keywords) => {
  const recommendations = [];

  if (words < 300) recommendations.push('Content too short. Aim for 300+ words.');
  if (readability < 60) recommendations.push('Content hard to read. Simplify.');
  if (keywords.main > 3) recommendations.push('Keyword density too high.');

  return recommendations;
};
Enter fullscreen mode Exit fullscreen mode

Real Performance Data

Before vs After Optimization

Site Performance Metrics:

Before:
- Lighthouse Score: 42/100
- LCP: 4.2 seconds
- FID: 280ms
- CLS: 0.35
- Organic Traffic: 2,000/month

After 3 months:
- Lighthouse Score: 96/100
- LCP: 1.6 seconds  
- FID: 45ms
- CLS: 0.03
- Organic Traffic: 28,000/month

ROI: 1,400% traffic increase
Enter fullscreen mode Exit fullscreen mode

SEO Impact

Ranking Improvements:
- Featured Snippets: 0 → 34
- Top 3 Rankings: 5 → 67
- Page 1 Rankings: 23 → 156
- Organic CTR: 1.8% → 4.2%
- Conversion Rate: 2.1% → 5.7%
Enter fullscreen mode Exit fullscreen mode

Monitoring & Automation

SEO Health Check

// lib/seoMonitor.js
export const runSEOAudit = async (url) => {
  const lighthouse = require('lighthouse');
  const chrome = await chromeLauncher.launch();

  const result = await lighthouse(url, {
    port: chrome.port,
    onlyCategories: ['performance', 'seo']
  });

  await chrome.kill();

  return {
    performance: result.lhr.categories.performance.score * 100,
    seo: result.lhr.categories.seo.score * 100,
    issues: extractSEOIssues(result.lhr.audits)
  };
};

// Weekly monitoring
const scheduleAudits = () => {
  cron.schedule('0 0 * * 1', async () => {
    const criticalPages = await getCriticalPages();
    const results = await Promise.all(
      criticalPages.map(page => runSEOAudit(page.url))
    );
    await sendSEOReport(results);
  });
};
Enter fullscreen mode Exit fullscreen mode

Advanced Tracking

Custom Events & Conversions

// Track micro-conversions
const trackEngagement = (action, element) => {
  gtag('event', 'engagement', {
    action: action,
    element: element,
    page: window.location.pathname,
    timestamp: Date.now()
  });
};

// Track scroll depth
let maxScroll = 0;
window.addEventListener('scroll', () => {
  const scrollPercent = Math.round(
    (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100
  );

  if (scrollPercent > maxScroll && scrollPercent % 25 === 0) {
    maxScroll = scrollPercent;
    gtag('event', 'scroll_depth', {
      scroll_depth: scrollPercent,
      page: window.location.pathname
    });
  }
});
Enter fullscreen mode Exit fullscreen mode

2024 SEO Strategy

Key Focus Areas

  1. Core Web Vitals - Direct ranking factor
  2. E-A-T Signals - Expertise, Authority, Trust
  3. User Experience - Bounce rate, dwell time
  4. Mobile-First - Primary indexing method
  5. Voice Search - Natural language optimization

Technical Implementation Priorities

// 1. Performance First
const performanceConfig = {
  LCP: '< 2.5s',
  FID: '< 100ms', 
  CLS: '< 0.1',
  TTI: '< 3.8s'
};

// 2. Structured Data
const requiredSchemas = [
  'Organization',
  'LocalBusiness', 
  'Product',
  'Article',
  'FAQ'
];

// 3. Technical SEO
const technicalChecklist = [
  'XML Sitemap',
  'Robots.txt',
  'SSL Certificate',
  'Mobile Responsive',
  'Page Speed',
  'Internal Linking',
  'Meta Tags',
  'Schema Markup'
];
Enter fullscreen mode Exit fullscreen mode

Conclusion

Technical SEO in 2024 is about:

Performance optimization as a ranking factor

Automation for scale and consistency

User experience metrics matter most

Data-driven decision making

Mobile-first everything

Start with Core Web Vitals, implement proper tracking, and automate what you can measure.


This guide represents 6 years of SEO experience managing 200+ websites with 10M+ organic impressions. What's working for your SEO strategy?

More resources:

Tags: #SEO #TechnicalSEO #WebPerformance #DigitalMarketing #NextJS #GoogleAnalytics

Top comments (1)

Collapse
 
stackedboost profile image
Peter Hallander

Really comprehensive breakdown. The performance and internal linking sections especially resonated.

One thing worth calling out for anyone applying this to Shopify specifically: prefetching is a technique that often gets overlooked in favor of standard speed optimizations. When a user hovers over a navigation link, you can preload that next page in the background so it loads instantly on click. This directly improves Interaction to Next Paint (INP) and reduces bounce from slow page transitions. I built a Shopify app called Prefetch (apps.shopify.com/prefetch) that implements exactly this — hover-based page prefetching for Shopify stores.

On the image side — Core Web Vitals are heavily influenced by image quality and loading. For Shopify product catalogs, inconsistent product images (varying backgrounds, sizes, quality) also hurt perceived trust. Eye Catching (apps.shopify.com/beautiful-brands) standardizes product image backgrounds and adds overlays/badges programmatically across the whole catalog.

For internal linking via a blog: Better Related Blog Posts (apps.shopify.com/better-related-blog-posts) automatically surfaces related articles at the bottom of each Shopify blog post — this directly supports the internal linking and dwell time signals you outlined.

And for stores running WordPress for content alongside Shopify, WP Simple WordPress Feed (apps.shopify.com/simple-wordpress-post-feed) syncs WP posts into Shopify to keep content accessible from the store.

(Disclosure: I built all four under Stackedboost.) Great guide — going to bookmark this one.