Π ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ²ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ ΡΠ΅Π»ΠΈΠ·Ρ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΡΡ Π΅ΠΆΠ΅Π΄Π½Π΅Π²Π½ΠΎ. ΠΠ΄Π½Π°ΠΊΠΎ Π΄Π°ΠΆΠ΅ Π½Π΅Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°Ρ Next.js, ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΈΠΈ ΠΈΠ»ΠΈ Nginx-ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ Π·Π°Π±Π»ΠΎΠΊΠΈΡΠΎΠ²Π°ΡΡ ΠΈΠ½Π΄Π΅ΠΊΡΠ°ΡΠΈΡ ΡΠ°ΠΉΡΠ°, ΡΠ»ΠΎΠΌΠ°ΡΡ ΠΊΠ°Π½ΠΎΠ½ΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠ΅Π³ΠΈ ΠΈΠ»ΠΈ ΡΡ ΡΠ΄ΡΠΈΡΡ ΠΏΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Core Web Vitals. ΠΠΎΠΈΡΠΊΠΎΠ²ΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΡ ΠΌΠ³Π½ΠΎΠ²Π΅Π½Π½ΠΎ ΡΠ΅Π°Π³ΠΈΡΡΡΡ Π½Π° ΡΠ°ΠΊΠΈΠ΅ ΡΠ±ΠΎΠΈ, Π° Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΡΡΠ΅ΡΡΠ½Π½ΠΎΠ³ΠΎ ΡΡΠ°ΡΠΈΠΊΠ° Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ ΠΌΠ΅ΡΡΡΡ.
ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ Π½Π°Π΄Π΅ΠΆΠ½ΡΠΉ ΡΠΏΠΎΡΠΎΠ± ΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠΈΡΡ ΠΏΡΠΎΠ΅ΠΊΡ β ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΡ Continuous SEO (Shift-Left SEO), Π²ΠΊΠ»ΡΡΠ°ΡΡΠ°Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ ΠΏΠΎΠΈΡΠΊΠΎΠ²ΠΎΠΉ Π²Π°Π»ΠΈΠ΄Π½ΠΎΡΡΠΈ ΠΊΠΎΠ΄Π° Π½Π΅ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²Π΅Π½Π½ΠΎ Π² ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π΅ CI/CD.
ΠΠΎΡΠ΅ΠΌΡ ΡΡΡΠ½ΠΎΠΉ SEO-ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ ΡΠ΅Π»ΠΈΠ·Π° Π±ΠΎΠ»ΡΡΠ΅ Π½Π΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ
Π’ΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΉ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΈΡΡ ΠΊ SEO-Π°ΡΠ΄ΠΈΡΠ°ΠΌ (ΡΡΡΠ½Π°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΠΎΡΠ»Π΅ Π΄Π΅ΠΏΠ»ΠΎΡ ΠΈΠ»ΠΈ ΡΠ°Π· Π² ΠΌΠ΅ΡΡΡ) ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΊΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠΈΡΠΊΠΈ Π΄Π»Ρ Π±ΠΈΠ·Π½Π΅ΡΠ°:
- ΠΠ°Π΄Π΅ΡΠΆΠΊΠ° Π²ΡΡΠ²Π»Π΅Π½ΠΈΡ ΡΠ±ΠΎΠ΅Π²: ΠΠΎΠΈΡΠΊΠΎΠ²ΡΠΉ Π±ΠΎΡ ΡΡΠΏΠ΅Π²Π°Π΅Ρ ΠΎΠ±ΠΎΠΉΡΠΈ ΡΠ»ΠΎΠΌΠ°Π½Π½ΡΡ Π²Π΅ΡΡΠΈΡ ΡΠ°ΠΉΡΠ° Π±ΡΡΡΡΠ΅Π΅, ΡΠ΅ΠΌ ΠΊΠΎΠΌΠ°Π½Π΄Π° Π·Π°ΠΌΠ΅ΡΠΈΡ ΠΏΡΠΎΠΏΠ°ΠΆΡ ΠΌΠ΅ΡΠ°-ΡΠ΅Π³ΠΎΠ²
titleΠΈΠ»ΠΈ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΠ΅ oindex`. - Π§Π΅Π»ΠΎΠ²Π΅ΡΠ΅ΡΠΊΠΈΠΉ ΡΠ°ΠΊΡΠΎΡ: ΠΡΠΈ Π½Π΅ΠΏΡΠ΅ΡΡΠ²Π½ΡΡ
ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΡ
staging-ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ Π»Π΅Π³ΠΊΠΎ Π·Π°Π±ΡΡΡ ΠΎΡΠΊΡΡΡΡ ΠΏΡΠΎΠ΄Π°ΠΊΡΠ΅Π½-Π²Π΅ΡΡΠΈΡ Π΄Π»Ρ ΡΠΊΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²
robots.txt. - Π’Π΅Ρ Π½ΠΈΡΠ΅ΡΠΊΠΈΠΉ Π΄ΠΎΠ»Π³: ΠΡΠΈΠ±ΠΊΠΈ Π²Π΅ΡΡΡΠΊΠΈ, ΡΠ½ΠΈΠΆΠ°ΡΡΠΈΠ΅ Lighthouse SEO score Π΄ΠΎ 70-80, Π½Π°ΠΊΠ°ΠΏΠ»ΠΈΠ²Π°ΡΡΡΡ Π½Π΅Π·Π°ΠΌΠ΅ΡΠ½ΠΎ.
ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ SEO-ΡΠ΅ΡΡΠΎΠ² Π² CI/CD ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠΈΡ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ ΠΊΠ°ΡΠ΅ΡΡΠ²Π° Π½Π° ΡΡΠ°ΠΏ Pull Request (PR). ΠΡΠ»ΠΈ PR Π»ΠΎΠΌΠ°Π΅Ρ ΡΡΡΡΠΊΡΡΡΡ ΠΌΠ΅ΡΠ°-ΡΠ΅Π³ΠΎΠ² ΠΈΠ»ΠΈ ΡΠ½ΠΈΠΆΠ°Π΅Ρ ΡΠΊΠΎΡΠΎΡΡΡ Π·Π°Π³ΡΡΠ·ΠΊΠΈ, merge Π² Π²Π΅ΡΠΊΡ main Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π±Π»ΠΎΠΊΠΈΡΡΠ΅ΡΡΡ.
ΠΠ°ΠΊΠΈΠ΅ SEO-ΠΌΠ΅ΡΡΠΈΠΊΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ Π² CI/CD
ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ SEO-Π°ΡΠ΄ΠΈΡ Π΄Π΅Π»ΠΈΡΡΡ Π½Π° ΡΡΠΈ ΡΡΠΎΠ²Π½Ρ ΠΏΡΠΎΠ²Π΅ΡΠΎΠΊ:
- HTML & Meta Validation: ΠΠ°Π»ΠΈΡΠΈΠ΅
title,description,canonical, H1, Π²Π°Π»ΠΈΠ΄Π½ΠΎΠΉ ΡΠ°Π·ΠΌΠ΅ΡΠΊΠΈ Open Graph ΠΈ JSON-LD (Schema.org). - Technical Server Health: ΠΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΡΡΡ HTTP-ΠΊΠΎΠ΄ΠΎΠ² ΠΎΡΠ²Π΅ΡΠ° (200 OK), ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠ΅ 301-ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡΡ, ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ ΡΠΈΠΊΠ»ΠΈΡΠ΅ΡΠΊΠΈΡ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡΠΎΠ² ΠΈ 404 ΠΎΡΠΈΠ±ΠΎΠΊ Π½Π° ΠΊΠ»ΡΡΠ΅Π²ΡΡ URL.
- Performance & Core Web Vitals: ΠΠ΅ΡΡΠΈΠΊΠΈ LCP (Largest Contentful Paint), CLS (Cumulative Layout Shift) ΠΈ INP (Interaction to Next Paint) ΡΠ΅ΡΠ΅Π· Lighthouse CI.
ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° CI/CD ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π° Π² GitHub Actions
ΠΠΈΠΆΠ΅ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΎΠ½Π½ΠΎΠ³ΠΎ ΡΠ°ΠΉΠ»Π° .github/workflows/seo-ci.yml, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°Π·Π²ΠΎΡΠ°ΡΠΈΠ²Π°Π΅Ρ ΡΠ΅ΡΡΠΎΠ²ΠΎΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅, Π·Π°ΠΏΡΡΠΊΠ°Π΅Ρ Lighthouse CI ΠΈ ΡΠΊΡΠΈΠΏΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΡ
:
name: Continuous SEO Audit Pipeline
on:
pull_request:
branches: [main, master]
jobs:
seo-validation:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Next.js Application
run: npm run build
- name: Run Lighthouse CI Audit
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
run: |
npx @lhci/cli collect --staticDistDir=./out || npx @lhci/cli collect --url=http://localhost:3000
npx @lhci/cli assert --assert.assertions.seo=error --assert.assertions.categories:seo='["error", {"minScore": 0.95}]'
- name: Execute Automated SEO Assertions
run: npx tsx scripts/assert-seo-tags.ts
ΠΠ°ΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΎΠ³ΠΎ ΡΠΊΡΠΈΠΏΡΠ° Π°Π²ΡΠΎΡΠ΅ΡΡΠΎΠ² SEO Π½Π° TypeScript
ΠΠ»Ρ Π³Π»ΡΠ±ΠΎΠΊΠΎΠΉ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ ΠΌΠΈΠΊΡΠΎΡΠ°Π·ΠΌΠ΅ΡΠΊΠΈ Schema.org ΠΈΠ»ΠΈ ΠΊΠ°Π½ΠΎΠ½ΠΈΠΊΠ°Π»ΠΎΠ²) ΠΌΡ Π² EvaLab ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π»Π΅Π³ΠΊΠΈΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠΊΡΠΈΠΏΡΡ Π½Π° Node.js ΠΈ Playwright.
// scripts/assert-seo-tags.ts
import { chromium } from 'playwright';
import assert from 'assert';
const TARGET_URLS = [
'http://localhost:3000/',
'http://localhost:3000/services',
'http://localhost:3000/blog'
];
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
for (const url of TARGET_URLS) {
console.log(`Checking SEO tags for: ${url}`);
const response = await page.goto(url);
// 1. ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠ°ΡΡΡΠ° ΠΎΡΠ²Π΅ΡΠ°
assert.strictEqual(response?.status(), 200, `URL ${url} did not return status 200`);
// 2. ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΠ΅Π³Π° Title
const title = await page.title();
assert.ok(title.length >= 30 && title.length <= 70, `Invalid title length on ${url}: ${title.length}`);
// 3. ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΠΌΠ΅ΡΠ°-ΡΠ΅Π³Π° Description
const description = await page.$eval('meta[name="description"]', el => el.getAttribute('content'));
assert.ok(description && description.length >= 100, `Description missing or too short on ${url}`);
// 4. ΠΡΠΎΠ²Π΅ΡΠΊΠ° Canonical ΡΠ΅Π³Π°
const canonical = await page.$eval('link[rel="canonical"]', el => el.getAttribute('href'));
assert.ok(canonical && canonical.startsWith('https://'), `Canonical URL invalid on ${url}: ${canonical}`);
// 5. ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΠΌΠ΅ΡΠ°-ΡΠ΅Π³Π° Robots
const robots = await page.$eval('meta[name="robots"]', el => el.getAttribute('content')).catch(() => null);
assert.ok(!robots || !robots.includes('noindex'), `Page ${url} contains noindex tag in production build!`);
}
await browser.close();
console.log('β
All Continuous SEO checks passed successfully!');
})();
Π§Π΅ΠΊ-Π»ΠΈΡΡ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ Continuous SEO Π² ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ²ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Π΅
| ΠΡΠ°ΠΏ | ΠΠ°Π΄Π°ΡΠ° | ΠΠ½ΡΡΡΡΠΌΠ΅Π½Ρ / ΠΠ΅ΡΠΎΠ΄ |
|---|---|---|
| Linting | ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π°Π»ΡΡΠΎΠ² Ρ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ ΠΈ H1-H6 Π² ΠΊΠΎΠ΄Π΅ | ESLint (eslint-plugin-jsx-a11y) |
| Staging Build | ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡΠΎΠ² ΠΈ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΡ Π½Π° ΡΠ΅ΡΡΠΎΠ²ΠΎΠΌ ΡΡΠ΅Π½Π΄Π΅ | Playwright / Node.js assertions |
| Performance | ΠΠΎΠ½ΡΡΠΎΠ»Ρ ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΈ Core Web Vitals Π΄ΠΎ ΡΠ΅Π»ΠΈΠ·Π° | Lighthouse CI (@lhci/cli) |
| Monitoring | ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ Π°Π»Π΅ΡΡΡ ΠΏΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ robots.txt Π½Π° prod | Cron Jobs + Telegram Bot Webhooks |
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΈ ΡΡΠ»ΡΠ³ΠΈ EvaLab
ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΡ SEO Π² CI/CD ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ΠΈΡΠΊΠ»ΡΡΠ°Π΅Ρ ΡΠΈΡΠΊ ΡΠ΅Π»ΠΎΠ²Π΅ΡΠ΅ΡΠΊΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ, Π³Π°ΡΠ°Π½ΡΠΈΡΡΡ, ΡΡΠΎ ΠΊΠ°ΠΆΠ΄Π°Ρ Π½ΠΎΠ²Π°Ρ Π²Π΅ΡΡΠΈΡ Π²Π°ΡΠ΅Π³ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π±ΡΠ΄Π΅Ρ ΠΈΠ΄Π΅Π°Π»ΡΠ½Π° Ρ ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ ΠΏΠΎΠΈΡΠΊΠΎΠ²ΡΡ Π°Π»Π³ΠΎΡΠΈΡΠΌΠΎΠ².
Π₯ΠΎΡΠΈΡΠ΅ Π½Π°ΡΡΡΠΎΠΈΡΡ Π½Π°Π΄Π΅ΠΆΠ½ΡΠΉ CI/CD ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΌΠΈ ΡΠ΅ΡΡΠ°ΠΌΠΈ SEO, ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΈ Π΄ΠΎΡΡΡΠΏΠ½ΠΎΡΡΠΈ Π΄Π»Ρ Π²Π°ΡΠ΅Π³ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΠ°? ΠΠ±ΡΠ°ΡΠΈΡΠ΅ΡΡ Π² EvaLab β ΠΌΡ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΡΠ΅ΠΌ Continuous SEO Π² ΠΏΡΠΎΡΠ΅ΡΡΡ Π²Π°ΡΠ΅ΠΉ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Β«ΠΏΠΎΠ΄ ΠΊΠ»ΡΡΒ»!
ΠΠ΅Π΄ΡΡΠΈΠΉ ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ ΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π²Π΅Π±-ΡΠΈΡΡΠ΅ΠΌ. Π‘ΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠ΅ΡΡΡ Π½Π° Next.js, ΡΠΈΡΡΠΎΠΉ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ΅, Core Web Vitals ΠΈ Π°Π»Π³ΠΎΡΠΈΡΠΌΠΈΡΠ΅ΡΠΊΠΎΠΌ ΡΠ°Π½ΠΆΠΈΡΠΎΠ²Π°Π½ΠΈΠΈ.


