Na hiszpańskim rynku naprawy urządzeń nikt nie robił programmatic SEO. Każda kombinacja urządzenia, marki, modelu, typu naprawy i miasta była niewykorzystaną okazją long-tail.
Teza: jeśli ktoś szuka „wymiana baterii iPhone Sewilla”, powinna istnieć dedykowana strona — z realną ceną, szacowanym czasem realizacji i zdjęciami z prawdziwych napraw. Ręczne budowanie tysięcy stron się nie skaluje. Potrzebowałem systemu, który generuje je automatycznie z ERP i wystarczająco mądrego, by zdecydować, które indeksować, a które pominąć.
Santifer iRepair to był mój serwis naprawy urządzeń w Sewilli od 2009 roku. Szesnaście lat, ponad 30 000 napraw. W 2024 uznałem, że strona musi wyjść poza broszurę na Squarespace i zacząć przechwytywać popyt już obecny w Google. Zbudowałem ten system programmatic SEO jako moat konkurencyjny i sprzedałem firmę we wrześniu 2025 — w szczycie wyników.
W 10 sekund
- ●Zbudowano 4730 statycznych landing page’y z produkcyjnego ERP (realne ceny, zdjęcia, zweryfikowane opinie)
- ●Silnik decyzji z DataForSEO: indeksowane są tylko strony z realnym wolumenem wyszukiwań
- ●Wynik: 2,26 mln wyświetleń, ponad 19 tys. kliknięć organicznych, 80% całego ruchu witryny
- ●7 miesięcy budowy, jedna osoba, sprzedaż na szczycie wyników
Okazja
Hiszpański rynek naprawy urządzeń jest hiper-lokalny. Ludzie szukają po mieście, marce i typie naprawy. Większość punktów miała jednak generyczne strony — jeden landing na całą Hiszpanię, o ile w ogóle miała stronę.
Tysiące kombinacji long-tail praktycznie bez konkurencji w SERP
Wyraźna intencja transakcyjna: użytkownik chce naprawy, nie informacji
Żaden konkurent w branży nie robił programmatic SEO w Hiszpanii (2024)
ERP miał już wszystko: 867 modeli, ceny, czasy realizacji, prawdziwe zdjęcia
Naturalna taksonomia biznesu (urządzenie, marka, model, naprawa, miasto) mapuje się wprost na URL-e
Prawdziwe zapytania z GSC
| Zapytanie | Kliknięcia | Imp. | CTR | Pos. |
|---|---|---|---|---|
| reparacion moviles sevilla | 42 | 1,947 | 2.2% | 2.5 |
| reparar iphone sevilla | 51 | 3,314 | 1.5% | 12.9 |
| reparacion iphone sevilla | 46 | 4,315 | 1.1% | 5.2 |
| cambiar bateria pixel 6a | 51 | 755 | 6.8% | 6.4 |
| servicio tecnico garmin sevilla | 36 | 534 | 6.7% | 6.5 |
| cambiar bateria apple watch | 37 | 3,967 | 0.9% | 11.7 |
Liczby
2.26M
Wyświetlenia
Łącznie (pomiar w Google Search Console)
19K+
Kliknięcia organiczne
Realny ruch z wyszukiwania organicznego (pomiar w Google Search Console)
4,730
Strony z ruchem
Spośród tysięcy wygenerowanych: 4084 indeksowalne w sitemapie, 4730 zebrało wyświetlenia
10.8x
Wzrost miesięczny
Z 202 do 2193 kliknięć/miesiąc w 11 miesięcy
80%
Kliknięcia z pSEO
Ruch organiczny pochodzi ze stron programmatic
7
Miesiące
1 osoba. CMS, pipeline’y, DataForSEO, 26 tys. obrazów i deploy
Budowa: marzec → październik 2024 (7 miesięcy). Jedna osoba. CMS, skrypty generacji, pipeline obrazów, integracja DataForSEO i wdrożenie — wszystko równolegle. Start produkcyjny: październik 2024. Gdybym budował to dziś z Claude Code, zajęłoby tydzień.

Dwie strategie, jeden system
Projekt zaczął się od ambicji ogólnokrajowych, ale Google miał inne zdanie. Wyszukiwania napraw mają silną intencję lokalną — Google faworyzuje wyniki blisko użytkownika, więc strony bez miasta nie konkurowały. Rozwiązanie: strategia dualna. Strony lokalne dla Sewilli (gdzie jest fizyczny punkt) oraz krajowe strony niszowe dla konkretnych napraw, gdzie lokalizacja ma mniejsze znaczenie.
Strony lokalne (Sewilla)
Kombinacje urządzenie + marka + naprawa z „/sevilla”. Google wyżej je pozycjonuje dzięki bliskości fizycznego punktu. Generują najwięcej ruchu.
Strony krajowe (bez miasta)
Niszowe naprawy, gdzie lokalizacja ma mniejsze znaczenie. Format „cambiar-{część}-{marka}-{model}” łapie zapytania informacyjne, które konwertują.
Architektura
System ma cztery warstwy. Airtable działa jako headless CMS z 14 tabelami i ~60 polami na tabelę. ERP zasila realnymi danymi produkcyjnymi. DataForSEO decyduje, co trafia do indeksu. Astro generuje statyczny HTML z minimalnym JS po stronie klienta — tylko to, co potrzebne do UX (wyszukiwarka, karuzela), ładowane lazy.
Airtable (headless CMS)
14 tabel, ~60 pól na tabelę. Hierarchia 6 poziomów: typ urządzenia, marka, rodzina, model, naprawa + warianty lokalne. Podwójne ceny (części oryginalne i kompatybilne), dziedziczenie obrazów, kaskadowy social proof.
ERP (dane produkcyjne)
Zasila Airtable realnymi danymi: zdjęcia before/after z prawdziwych napraw, zweryfikowane opinie klientów, aktualny stan części. 867 modeli, 20+ marek, 15+ typów naprawy.
DataForSEO (silnik decyzji)
Pobiera realne wolumeny wyszukiwań dla każdej kombinacji. Pole „indexable” w Airtable jest napędzane bezpośrednio tymi danymi. Brak wolumenu = brak indeksacji.
Astro (generacja statyczna)
21 szablonów stron. Generuje statyczny HTML z minimalnym JS ładowanym lazy. 6 typów JSON-LD na stronę. SEO obrazów z wstrzykiwaniem EXIF. Deploy na Cloudflare CDN.
Taksonomia URL
Serwis używa 6 wzorców URL, każdy odpowiadający poziomowi taksonomii biznesowej. Wzorce lokalne (z /sevilla) łapią intencję lokalną. Wzorce krajowe (bez miasta) łapią wyszukiwania niszowe.
/reparar-{device}/{city}
/reparar-{device}/{brand}/{city}
/reparar-{device}/{repair-type}/{city}
/reparar-{device}/{brand}/{repair-type}/{city}
/reparar-{device}/{model}/{repair-type}
/cambiar-{repair}-{brand}-{model}
Premiumowe trasy Apple
Od 2009 naprawialiśmy wyłącznie urządzenia Apple — ludzie nas z tego znali. Apple ma najwyższy wolumen wyszukiwań, a krótsze trasy oddają ten priorytet: /iphone/14-pro zamiast /reparar-movil/apple/iphone-14-pro. Krócej, czyściej, lepszy CTR. Jedna flaga boolean zmienia wszystko:
// Apple: /iphone/14-pro (short, clean, better CTR) const records = await getRecordsModelos(true); // modoApple = true → CMSAstro(Apple) view return records.map(r => ({ params: { paramMarcaApple: r.paramMarca, paramModeloApple: r.paramModelo }, })); // Generic: /reparar-movil/samsung/galaxy-s21 const records = await getRecordsModelos(); // modoApple = false → CMSAstro view return records.map(r => ({ params: { paramTipo: r.paramTipo, paramMarca: r.paramMarca, paramModelo: r.paramModelo }, }));
modoApple = true
Jedna flaga boolean przełącza widok Airtable (CMSAstro vs CMSAstro(Apple)) i strukturę URL. Ta sama strona, ten sam layout, dwa systemy routingu.
Krótsze trasy
/iphone/14-pro vs /reparar-movil/apple/iphone-14-pro. Apple is the dominant brand in repairs; its routes deserve premium URLs.
Wewnątrz CMS
Airtable to nie tylko „arkusz na sterydach”. Tutaj działa jak pełny relacyjny CMS. Klucz: hierarchia 6 poziomów, która dokładnie odzwierciedla sposób działania firmy.
| Tabela | Cel | Kluczowe pola |
|---|---|---|
| Typy urządzeń | Poziom główny taksonomii | slug, name, SEO description, menu order |
| Marki | Marki powiązane z typami urządzeń | slug, name, logo, compatible types |
| Rodziny | Grupowanie modeli (np. seria iPhone 14) | slug, hero image (inheritable), brand |
| Modele | Konkretne urządzenia z cenami | slug, family, image (inherits from family if empty), year |
| Naprawy | Typy napraw per model | slug, original price, compatible price, turnaround, indexable |
| Warianty lokalne | Strony miejskie pod lokalne SEO | model + repair + city, adjusted price, availability |

Ten CMS z 14 tabelami jest częścią większego Airtable Business OS (12 baz), który prowadził całą firmę: magazyn, CRM, księgowość, HR i więcej. Przeczytaj pełne case study Business OS →
Kluczowe wzorce CMS
Podwójne ceny
Każda naprawa ma cenę z częściami oryginalnymi i cenę z kompatybilnymi. Użytkownik wybiera na landing page.
Dziedziczenie obrazów
Jeśli model nie ma obrazu, dziedziczy go z rodziny. Mniej utrzymania, żadnych pustych stron.
Kaskadowy social proof
Opinie łączą się na poziomie modelu, rodziny lub marki. Opinia o „iPhone 14 Pro” pojawia się na każdej stronie naprawy tego modelu.
Tryb bridge
Wycofane naprawy nie są usuwane — dostają flagę „bridge” i przekierowują do najbliższej alternatywy. Zero 404, zero utraty autorytetu.

Anatomia strony
Każda z ponad 4700 stron powstaje z szablonu, ale treść jest unikalna, bo pochodzi z ERP. To nie tekst generowany AI ani wypełniacz — to dane produkcyjne.
Breadcrumb + schema
Hierarchiczna nawigacja odzwierciedlająca taksonomię. Automatycznie generuje BreadcrumbList JSON-LD.
Realne ceny
Ceny oryginalne i kompatybilne, pobrane z ERP. Użytkownik widzi dokładnie, ile zapłaci.
Szacowany czas realizacji
Na podstawie realnych, historycznych danych napraw. Nie generyczny zgadywak.
Zdjęcia before/after
Prawdziwe zdjęcia z ukończonych napraw. EXIF z geolokalizacją i metadanymi SEO.
Zweryfikowane opinie
Prawdziwe opinie klientów powiązane z modelem lub rodziną. Ze schemą Review i AggregateRating.
6 typów JSON-LD
LocalBusiness, Product, Service, BreadcrumbList, FAQStrona, AggregateRating. Każda strona ma pełny markup.



Ścieżka konwersji na stronie
Każda strona ma strukturę konwersji zaprojektowaną tak, by przeprowadzić użytkownika od odkrycia do działania:
Hero z podwójnymi cenami (oryginał/kompatybilne) + bezpośrednie CTA rezerwacji
Specyfikacje modelu: aparat, bateria, technologie urządzenia
Galeria prawdziwych zdjęć before/after napraw
Zweryfikowane opinie klientów powiązane z modelem lub rodziną
FAQ generowane z danych ERP (prawdziwe pytania klientów)
Końcowe CTA z mapą punktu i przyciskiem rezerwacji
Użytkownik szuka „naprawa ekranu iPhone 14 Pro Sewilla”. Trafia na stronę z cenami (189 € oryginał / 89 € kompatybilne), szacowanym czasem (45 min), 3 prawdziwymi zdjęciami naprawy iPhone 14 Pro i 12 zweryfikowanymi opiniami. Bez zbędnej nawigacji — wszystko potrzebne do decyzji jest na miejscu.
Dynamiczny copy per model
Każdy model dostaje unikalny microcopy wygenerowany z realnych parametrów sprzętu. Pole w Airtable trzyma specyfikację (aparat, bateria, procesor, odporność na wodę), a prompt generuje opis różniący się per model. iPhone 14 Pro mówi o aparacie 48 MP i wyświetlaczu ProMotion. Pixel 7a podkreśla chip Tensor i fotografię obliczeniową. To nie generyczny wypełniacz — to copy, który dotyczy TYLKO tego modelu, na podstawie realnych danych sprzętowych. Ten sam szablon, unikalna treść na każdej stronie.

Live pricing z ERP
Ten sam CMS, który generuje copy, synchronizuje też ceny napraw w czasie rzeczywistym. Airtable łączy ERP (gdzie aktualizowane są koszty części i marże) ze stroną. Każda karta modelu pokazuje zakres cen z min i max dostępnych napraw. Gdy cena zmienia się w ERP, rebuild strony wgrywa nową cenę — zero ręcznej interwencji.

let cadenaPrecio = ''; if (mostrarPrecio.startsWith('desde') && detail.precioMinCard) { cadenaPrecio = `Desde ${detail.precioMinCard}`; } if (mostrarPrecio === 'desdeHasta' && detail.precioMaxCard) { cadenaPrecio = `${cadenaPrecio} hasta ${detail.precioMaxCard}`; } if (mostrarPrecio === 'exacto' && detail.precioMinCard) { cadenaPrecio = detail.precioMaxCard ? `Desde ${detail.precioMinCard} hasta ${detail.precioMaxCard}` : `${detail.precioMinCard}`; }
Trzy tryby cen
„desde” (tylko minimum), „desdeHasta” (pełny zakres), „exacto” (stała cena lub zakres z CTA). Tryb konfiguruje się per typ strony.
precioMinCard / precioMaxCard
Pola wyliczane w Airtable: agregują min i max ze wszystkich dostępnych napraw modelu. Gdy koszt części zmienia się w ERP, pola przeliczają się automatycznie.
Wyszukiwanie świadome kontekstu
Pasek wyszukiwania to nie prosty filtr tekstowy. Działa na własnym algorytmie scoringu — bez zewnętrznych bibliotek typu Fuse.js. Użytkownik wpisuje „iphone 12 pro”, a system ocenia wszystkie 867 modeli: +20 jeśli wszystkie słowa pasują, +30 za dokładne dopasowanie, +10 jeśli nazwa modelu zaczyna się od zapytania, i karze dodatkowe słowa w nazwie. Wynik: 6 najbardziej trafnych modeli, posortowanych po wyniku.


Ciekawe jest to, że wyszukiwanie jest świadome kontekstu. Na stronie głównej przeszukuje wszystkie 867 modeli ze wszystkich marek i typów. Na stronie marki (np. Samsung) — tylko modele Samsung. Na stronie typu urządzenia (np. tablety) — tylko tablety. Ten sam komponent, z propsami filtrów (`filtroTipo`, `filtroMarca`), zachowuje się inaczej w zależności od miejsca osadzenia. Modele ładują się lazy przy pierwszym fokusie inputu i cache’ują w localStorage, więc kolejne wyszukiwania są natychmiastowe.
Oto prawdziwa funkcja scoringu — 30 linii, zero zależności:
function calcularPuntuacion(modelo, terminosBusqueda) { let puntuacion = 0; const nombreModelo = modelo.n.toLowerCase(); const todasPresentes = terminosBusqueda.every(t => nombreModelo.includes(t)); if (todasPresentes) { puntuacion += 20; const palabrasModelo = nombreModelo.split(/\s+/); const extras = palabrasModelo.filter(p => !terminosBusqueda.includes(p)).length; puntuacion -= extras * 2; if (nombreModelo === terminosBusqueda.join(' ')) puntuacion += 30; if (nombreModelo.startsWith(terminosBusqueda.join(' '))) puntuacion += 10; } return puntuacion; }
+20 baza
Wszystkie terminy muszą być obecne. „iphone 12 pro” pasuje do „Apple iPhone 12 Pro”, ale nie do „Apple iPhone 12”.
−2 za dodatkowe słowo
Karze długie nazwy. „Apple iPhone 12 Pro Max” dostaje niższy wynik niż „Apple iPhone 12 Pro” dla zapytania „iphone 12 pro”.
+30 dokładne, +10 starts-with
Dokładne dopasowania dominują. 30 linii, zero zależności, w tej domenie lepsze niż Fuse.js.
Silnik decyzji
System generuje tysiące stron (znacznie więcej niż 4730, które dostały ruch), ale nie wszystkie zasługują na indeksację. Jeśli nikt nie szuka „naprawa kamery przedniej iPhone 11”, ta strona nie powinna konkurować w Google — ale musi istnieć dla użytkownika przeglądającego stronę iPhone 11, który właśnie tej naprawy potrzebuje. Klucz: oddzielenie SEO od UX. Silnik decyzji odpytuje DataForSEO o realny wolumen dla każdej kombinacji i zapisuje wynik w polu „indexable” w airtable.ts.
Wysoki wolumen (DataForSEO) → strona indeksowalna
Jeśli słowo kluczowe ma istotny wolumen, strona powstaje z meta robots „index, follow”, trafia do sitemapy i dostaje priorytetowe linkowanie wewnętrzne.
Niski lub zerowy wolumen → strona noindex (tylko UX)
Strona istnieje pod UX i nawigację wewnętrzną, ale ma meta robots „noindex” i jest wyłączona z sitemapy.
Brak danych usługi w ERP → strona nie powstaje
Jeśli nie ma realnych danych usługi (cena, dostępność), strona nie jest budowana. Zero thin content.
Wycofana naprawa → przekierowanie bridge
Strona dostaje flagę „bridge” i zwraca 301 do najbliższej alternatywy. Chroni zgromadzony autorytet.
System generuje łącznie tysiące stron. Z nich 4084 trafiło do sitemapy jako indeksowalne. 4730 zebrało wyświetlenia z Google. Reszta nie jest indeksowana, ale nadal istnieje dla użytkownika nawigującego po serwisie.

Optymalizacja crawl budget
Przy ponad 4700 stronach zarządzanie crawl budgetem jest krytyczne — zgodnie z dokumentacją Google Search Central. Google nie powinien marnować czasu na strony, które nie będą rankować. Ponad 700 reguł robots.txt dokłada się do 1009 przekierowań odziedziczonych po migracji.
Selektywny noindex z DataForSEO
Pole „indexable” w Airtable jest zasilane bezpośrednio danymi wolumenu z DataForSEO. Strony bez wolumenu dostają noindex. To nie arbitralna decyzja — to podejście data-driven.
Filtrowana sitemap (4084 URL-e)
sitemap.xml zawiera tylko URL-e indeksowalne. Spośród 4730 stron z wyświetleniami tylko 4084 trafiło do sitemapy. Google nie odkrywa reszty tym kanałem.
Struktura URL z 6 wzorcami
Każdy poziom taksonomii ma przewidywalny wzorzec URL. Google rozumie hierarchię bez zgadywania.
Kontekstowe linkowanie wewnętrzne
Strony indeksowalne dostają więcej linków wewnętrznych. Strony miast linkują do dostępnych napraw, modele do swoich napraw, rodziny agregują modele.
Przekierowania bridge dla wycofanych pozycji
Zamiast zwracać 404 przy wycofanej naprawie, robi 301 do najbliższej alternatywy. Ponad 700 reguł przekierowań w vercel.json. Zero utraty autorytetu, zero martwych linków.
Wzorzec „Safe Noindex”
Przypadkowy noindex to jeden z najdroższych błędów SEO — jedna linia może zdeindeksować tysiące stron. Oto jak temu zapobiegliśmy:
{NOINDEXCUIDADO && NOINDEXCUIDADO === 'Estoy absolutamente seguro que no quiero hacer no index por eso pongo esta cadena' && ( <meta name="robots" content="noindex" /> )}
String, nie boolean
Boolean może być true przez przypadek (złe pole, domyślna wartość, błąd migracji). 80-znakowy hiszpański string wymaga świadomej intencji.
Podwójna straż
Prop musi być truthy ORAZ dokładnie równy stringowi. Nawet ustawiony na „true” lub 1 — tag noindex się nie wyrenderuje.
Dwa lata na produkcji. Zero przypadkowych deindeksacji. 80-znakowy hiszpański string zrobił swoje.
Pipeline budowy
Pipeline zamienia dane CMS w gotowy do deployu statyczny serwis. W pełni zautomatyzowany. Sam schema.ts ma 1677 linii mapujących hierarchię Airtable na typy Astro.
Airtable API
Ekstrakcja rekordów z retry i exponential backoff
Mapowanie schema
1677 linii transformujących hierarchię 6 poziomów na typy TypeScript
Cache opinii
Opinie są cache’owane, by unikać zbędnych wywołań API
getStaticPaths
Generuje statyczne trasy z pełnej taksonomii
ReparacionLayout
21 szablonów stron renderowanych według poziomu taksonomii
Astro SSG
Statyczny build z minimalnym JavaScriptem ładowanym lazy
Optymalizacja
Skompresowane obrazy, wstrzykiwanie EXIF, filtrowana sitemap, linkowanie wewnętrzne
Cloudflare CDN
Deploy z invalidacją cache i globalnym cache’owaniem edge
Retry z exponential backoff
Pipeline zaczyna od pobrania danych z Airtable. Czternaście tabel, tysiące rekordów — wywołania API muszą być odporne. Jedna generyczna funkcja obsługuje wszystko:
function delay(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } async function retryWithBackoff<T>( operation: () => Promise<T>, retries: number = 5, delayTime: number = 500 ): Promise<T> { try { return await operation(); } catch (error: any) { if (retries > 0 && (error.statusCode === 502 || error.statusCode === 503)) { await delay(delayTime); return retryWithBackoff(operation, retries - 1, delayTime * 2); } throw error; } }
Generic <T>
Jedna funkcja dla każdego typu rekordu (ITipos, IMarcas, IModelos, IReparaciones...).
Tylko 502/503
Retry tylko przy błędach serwera (Bad Gateway, Service Unavailable). Błędy klienta (400, 401) padają od razu.
delayTime * 2
Exponential backoff: 500 ms → 1 s → 2 s → 4 s → 8 s. 5 prób = max 15,5 s przed poddaniem się.
System cache’u opinii
Opinie to najdroższe wywołania w buildzie: ponad 4700 stron może ich potrzebować, ale istnieje tylko 607. Ładujemy je raz na starcie builda, a każda strona czyta z pamięci:
let caches: { [key: string]: Reseña[] | undefined } = {}; async function loadReseñas(baseName: string, cacheKey: string): Promise<void> { if (caches[cacheKey]) return; const fetchOperation = () => new Promise<Reseña[]>((resolve, reject) => { const allRecords: Reseña[] = []; base(baseName) .select({ view: 'CMSAstro', fields: ReseñaFields }) .eachStrona( (records, fetchNextStrona) => { records.forEach(record => allRecords.push(mapReseñaFields(record.fields))); fetchNextStrona(); }, (err) => err ? reject(err) : resolve(allRecords) ); }); caches[cacheKey] = await retryWithBackoff(fetchOperation); } export async function ensureCachesLoaded(): Promise<void> { await Promise.all([ loadReseñas('Reseñas sincronizar Astro', 'cachedReseñas'), loadReseñas('Reseñas Internas', 'cachedReseñasInternas') ]); } // Runs on module import ensureCachesLoaded().catch(console.error);
Wywołanie na poziomie modułu
ensureCachesLoaded() uruchamia się przy imporcie modułu. W Astro SSG wszystkie opinie ładują się do pamięci przed generacją stron.
Promise.all
Oba źródła (Google My Business + wewnętrzne ankiety) ładują się równolegle.
Trade-off: O(n) find
Strony szukają po ID przez .find(). Skan liniowy, ale przy 607 opiniach eliminuje setki wywołań API. Właściwy trade-off dla pipeline’u budowy.
Zautomatyzowany pipeline treści
Wygenerowanie tysięcy stron to połowa roboty. Każda potrzebuje unikalnych obrazów, metadanych i copy. Osiem skryptów Node.js (łącznie 1411 linii) automatyzuje całą produkcję wizualną i tekstową — zero pracy ręcznej. Wszystko łączy się z 12 bazami Airtable w Business OS. Wynik: ponad 26 000 automatycznie wygenerowanych obrazów.
Parametryczna generacja obrazów
Jedno zdjęcie urządzenia automatycznie daje 18 wariantów — po jednym na typ naprawy (ekran, bateria, aparat, port ładowania...) plus obraz generyczny. Zdjęcia urządzeń pochodzą z GSM Arena i są składane z PNG overlayami napraw. 867 modeli × 18 wariantów = ponad 15 500 unikalnych obrazów, bez Photoshopa.
Wstrzykiwanie EXIF pod lokalne SEO
Każdy obraz dostaje współrzędne GPS Sewilli i opis SEO wstrzyknięty do metadanych EXIF. Google Images czyta je pod ranking lokalny. Automatyzacja: piexifjs i kodowanie UCS-2.
Pipeline zdjęć before/after
Ponad 10 000 prawdziwych zdjęć napraw przetwarzanych automatycznie. Pobrane z Airtable, przeskalowane, z rozmytym tłem, złożone do WebP, a wynikowe URL-e zapisane z powrotem do Airtable. Dwukierunkowe ETL: Airtable → przetwarzanie → Airtable.
Dynamiczny copy per model
Każdy model ma pole z realnymi parametrami sprzętu (aparat, bateria, procesor). Prompt zamienia je w unikalny microcopy dla każdej strony. To nie AI „wymyślające treść” — to AI opisujące realne dane sprzętowe. Każda strona czyta się inaczej, bo każde urządzenie JEST inne.
Każdy obraz naprawy dostaje współrzędne GPS punktu wstrzyknięte do metadanych EXIF. Google Images używa tych danych, by pokazywać obrazy w wynikach lokalnych:
// Shop coordinates in Seville gps[piexif.GPSIFD.GPSLatitude] = convertToDMS(37.38606); gps[piexif.GPSIFD.GPSLatitudeRef] = 'N'; gps[piexif.GPSIFD.GPSLongitude] = convertToDMS(-5.98585); gps[piexif.GPSIFD.GPSLongitudeRef] = 'W'; // SEO description in both EXIF fields exifObj['0th'][piexif.ImageIFD.ImageDescription] = description; // UCS-2 for Unicode support (Spanish accents, ñ) const userComment = Buffer.concat([ Buffer.from('UNICODE\0\0\0', 'ascii'), encodeUCS2(description), ]); exifObj['Exif'][piexif.ExifIFD.UserComment] = userComment.toString('binary');
Stałe GPS
Każdy obraz naprawy dostaje dokładne współrzędne punktu w Sewilli. Google Images używa EXIF GPS do wyników lokalnych.
Podwójny opis
Tekst SEO trafia do ImageDescription (standardowy EXIF) i UserComment (rozszerzony EXIF). Różne parsery czytają różne pola.
Kodowanie UCS-2
Hiszpańskie znaki (akcenty, ñ) wymagają Unicode. Specyfikacja EXIF wymaga UCS-2 z prefiksem UNICODE\0\0\0.

Kaskada treści: jedna opinia, sześć stron
System automatycznie dziedziczy treść przez taksonomię. Opinia o „naprawie ekranu iPhone 12” nie pojawia się tylko na tej stronie — pokazuje się wszędzie, gdzie jest istotna:
| Strona | Poziom |
|---|---|
| /reparar-movil/apple/iphone-12/pantalla/sevilla | Model + naprawa + miasto |
| /reparar-iphone/pantalla/sevilla | Urządzenie + naprawa + miasto |
| /reparar-movil/apple/sevilla | Urządzenie + marka + miasto |
| /reparar-iphone/sevilla | Urządzenie + miasto |
| /reparar-movil/pantalla/sevilla | Urządzenie + naprawa + miasto |
| /reparar-movil/sevilla | Urządzenie + miasto |
Ta sama logika dotyczy zdjęć before/after: zdjęcie z naprawy ekranu iPhone 12 pojawia się na każdej stronie w tej gałęzi taksonomii. Mnoży unikalną treść bez sztucznego duplikowania ani generowania. Każda strona zbiera więcej social proof i treści wizualnej wraz ze wzrostem firmy.
Ponad 26 000 automatycznie wygenerowanych obrazów. 867 modeli po 18 wariantów. Ponad 10 000 prawdziwych zdjęć napraw. Zero ręcznej interwencji. 12 baz Business OS zasila cały pipeline.
Zobacz skrypty pipeline’u na GitHubie →
Wewnątrz pipeline’u obrazów
Poprzednia sekcja opisuje pipeline na wysokim poziomie. Tu widać dokładnie, jak działa: prawdziwe szablony overlay, kod kompozycji i co się dzieje przy uruchomieniu na 867 różnych modelach.
Szablony overlay
Każdy typ naprawy ma PNG overlay 384×256 px. Overlay wizualnie pokazuje, która część jest naprawiana: pęknięty ekran, bateria, aparat... Łącznie 17 szablonów, każdy zaprojektowany do złożenia na dowolne zdjęcie urządzenia.












Proces kompozycji
Każdy obraz naprawy powstaje w 6 krokach, w pełni automatycznie skryptem Node.js i Sharp.js:
Pobierz zdjęcie urządzenia
Oficjalne zdjęcie urządzenia jest pobierane z GSM Arena i przechowywane tymczasowo.
Utwórz biały canvas 384×256
Sharp.js tworzy pustą bazę 384×256 px z kanałem alfa.
Nałóż PNG naprawy
Szablon naprawy (ekran, bateria itd.) jest składany jako pierwsza warstwa na canvasie.
Wycentruj urządzenie przy x=96
Zdjęcie urządzenia jest proporcjonalnie skalowane i centrowane przy x=96, zostawiając miejsce na overlay po prawej.
Eksport do WebP
Wynik eksportowany jako zoptymalizowany WebP. Każdy obraz waży ~5–8 KB.
Powtórz ×17 napraw + hero
Proces powtarza się dla wszystkich 17 typów naprawy plus generyczny hero 256×256. Razem: 18 obrazów na model.
Prawdziwy kod
To prawdziwy fragment z generarImagenesReparacionesModelos.mjs który generuje każdy obraz naprawy:
await sharp({ create: { width: 384, height: 256, channels: 4, background: { r: 255, g: 255, b: 255, alpha: 1 } } }) .png() .composite([ { input: overlayPath }, { input: devicePhoto, top: Math.round(top), left: Math.round(left) } ]) .webp() .toFile(outputPath)
Canvas
Tworzy pusty obraz 384×256 z białym tłem i kanałem alfa. To canvas, na którym wszystko jest składane.
Kolejność kompozycji
Najpierw overlay (szablon naprawy), potem zdjęcie urządzenia. Kolejność ma znaczenie: overlay siedzi za urządzeniem.
Pozycjonowanie
Zdjęcie urządzenia jest centrowane w pionie i ustawione przy x≈96. Zostawia miejsce, by overlay naprawy był widoczny po prawej.
1 zdjęcie → 18 wariantów
Z jednego zdjęcia iPhone 14 Pro pipeline automatycznie generuje 18 unikalnych obrazów: jeden generyczny hero i 17 wariantów naprawy. Każdy wariant składa zdjęcie urządzenia z konkretnym overlayem.


Wymiana ekranu iPhone 14 Pro

Wymiana baterii iPhone 14 Pro

Wymiana tylnego aparatu iPhone 14 Pro

Wymiana portu ładowania iPhone 14 Pro

Wymiana tylnej pokrywy iPhone 14 Pro

Wymiana szkła iPhone 14 Pro

Wymiana głośnika iPhone 14 Pro

Wymiana mikrofonu iPhone 14 Pro

Wymiana słuchawki iPhone 14 Pro
9 z 17 automatycznie wygenerowanych wariantów dla iPhone 14 Pro. Każdy obraz składa prawdziwe zdjęcie urządzenia z konkretnym overlayem naprawy.
Ten sam pipeline, inne urządzenie
Ten sam proces działa dla dowolnego urządzenia. Zmienia się zdjęcie, overlaye zostają. Dlatego da się skalować do 867 modeli bez pracy ręcznej.





Skala
867
Modele
Unikalne urządzenia z wygenerowanymi obrazami
17
Overlaye
Szablony napraw (ekran, bateria, aparat...)
18
Obrazy/model
17 napraw + 1 hero na urządzenie
15,606
Kompozycje
Łącznie automatycznie wygenerowanych obrazów
Pipeline opinii
Opinie to najsilniejszy social proof na każdej stronie. Ale zarządzanie setkami profili klientów, synchronizacja dwóch źródeł i kaskadowanie sygnałów zaufania przez całą taksonomię wymaga własnego pipeline’u.
Źródło i synchronizacja
Opinie pochodzą z dwóch źródeł: Google My Business (publicznie zweryfikowane) oraz wewnętrznych ankiet po naprawie. Oba synchronizują się do Airtable i normalizują do jednego formatu.
| Tabela | Źródło | Kluczowe pola |
|---|---|---|
| Reseñas sincronizar Astro | Google My Business | quote, name, rating, imageUrl, response |
| Reseñas Internas | Ankiety po naprawie | quote, name, rating, imageUrl, linked model |
Przetwarzanie zdjęć profilowych
Każda opinia ze zdjęciem profilowym przechodzi przez zautomatyzowany pipeline:
Pobierz zdjęcie z Airtable
URL zdjęcia profilowego jest pobierany z pola załącznika w Airtable.
Konwertuj do WebP jakość 95
Sharp.js konwertuje obraz do WebP w jakości 95, by zachować detale twarzy.
Zapisz do /bg/res/
Plik zapisywany jest z semantyczną nazwą: reparacion-{type}-{model}-{name}-{date}.webp
Zapisz URL z powrotem do Airtable
Wynikowy URL jest zapisywany z powrotem do odpowiadającego pola. Dwukierunkowe ETL.
Prawdziwy kod
To prawdziwy fragment z `generarImagenesReseñas.mjs`, który przetwarza każde zdjęcie profilowe:
const imageBuffer = await fetch(attachmentUrl) .then(r => r.arrayBuffer()) await sharp(Buffer.from(imageBuffer)) .webp({ quality: 95 }) .toFile(outputPath) // Write processed URL back to Airtable await base('Reseñas sincronizar Astro') .update(record.id, { 'imagen_procesada': outputUrl })
Zachowanie wymiarów
Bez skalowania — zdjęcia profilowe zachowują oryginalne wymiary dla maksymalnej jakości w karuzeli.
Jakość WebP 95
Wyższa jakość niż przy zdjęciach napraw (85), bo zdjęcia profilowe są mniejsze, a detale mają większe znaczenie.
Dwukierunkowe ETL
Airtable jest jednocześnie źródłem I celem: zdjęcie jest pobierane, przetwarzane, a wynikowy URL wraca do rekordu.
Kaskada social proof
Opinie nie pojawiają się tylko na jednej stronie — dziedziczą się przez całą taksonomię. Opinia powiązana z modelem propaguje się na każdą stronę, gdzie ten model jest istotny.
Opinia „iPhone 14 Pro” → pojawia się na każdej stronie naprawy tego modelu, w każdym mieście
Opinia rodziny „iPhone 14” → pojawia się na wszystkich modelach rodziny (14, 14 Plus, 14 Pro, 14 Pro Max)
Opinia marki „Apple” → pojawia się na zagregowanych stronach marki, np. /reparar-movil/apple/sevilla
Kaskada jest automatyczna: powiąż opinię z właściwym poziomem, a build ją rozdystrybuuje
Setki przetworzonych profili
Prawdziwe profile klientów przetworzone przez pipeline. Każde zdjęcie pobrano, skonwertowano do WebP i powiązano z powrotem z Airtable.









Prawdziwe profile klientów. Każde zdjęcie jest pobierane, konwertowane do WebP i powiązywane z powrotem z Airtable.
Renderowanie: karuzela CRO
Na produkcji opinie renderują się w karuzeli z auto-rotacją co 9 s, wizualnym paskiem postępu i nawigacją kropkami. Top 20 opinii widać od razu; reszta rozwija się pod przyciskiem „Pokaż więcej”. Wszystko server-rendered — zero JavaScriptu dla bazowej karuzeli.

1 / 5
Automatyczny filtr: najpierw pojawiają się tylko opinie ≥5★ z napisanym komentarzem. Opinie bez tekstu lub poniżej 5 gwiazdek lądują poniżej foldu.
Skala
600+
Przetworzone profile
Zdjęcia profilowe skonwertowane do WebP
2
Źródła
Google My Business + ankiety wewnętrzne
9s
Rotacja
Interwał auto-rotacji karuzeli CRO
≥5★
Priorytet
Najpierw opinie 5★ z komentarzem
Pipeline before/after
Każda ukończona naprawa generuje dowód fotograficzny: 4 zdjęcia dokumentujące stan urządzenia przed i po. Ten pipeline przetwarza je automatycznie i rozsyła po serwisie.
Protokół zdjęć
Każda ukończona naprawa w punkcie ma protokół 4 zdjęć:
Front przed
Zdjęcie frontu urządzenia przed naprawą. Pokazuje widoczne uszkodzenia (pęknięty ekran, ślady itd.).
Front po
Zdjęcie frontu po naprawie. Ten sam kąt do bezpośredniego porównania.
Tył przed
Zdjęcie tyłu przed naprawą. Dokumentuje ogólny stan urządzenia.
Tył po
Zdjęcie tyłu po naprawie. Domknięcie dokumentacji wizualnej.
Flaga `difuminar` w Airtable oznacza zdjęcia wymagające rozmycia: ekrany z powiadomieniami, danymi osobowymi itd. Rozmycie nakładane jest automatycznie w pipeline.
Automatyczne przetwarzanie
Każde zdjęcie przechodzi 6 kroków przetwarzania Sharp.js:
Pobierz z Airtable
Oryginalne zdjęcie pobierane jest z pola załącznika rekordu naprawy.
Skaluj do rozdzielczości 1/4
Obraz skalowany do 25% oryginalnego rozmiaru. Wystarczy na web, dramatycznie tnie wagę pliku.
Warunkowe rozmycie (sigma 8)
Jeśli flaga `difuminar` jest ustawiona, nakładany jest Gaussian blur sigma 8. Chroni dane osobowe widoczne na ekranie.
Półprzezroczysty biały overlay
Warstwa 30% bieli jest składana na tle dla spójnego kontrastu i czystego wyglądu.
Eksport do WebP jakość 85
Jakość 85 — niższa niż przy zdjęciach profilowych (95), bo przy rozdzielczości 1/4 dodatkowy detal i tak nie jest zauważalny.
Zapisz slug z powrotem
Przetworzona nazwa pliku wraca do Airtable, żeby build Astro mógł ją znaleźć.
Prawdziwy kod
To prawdziwy fragment z CasosExito.mjs który przetwarza każde zdjęcie naprawy:
let pipeline = sharp(inputBuffer) .resize({ width: Math.round(metadata.width / 4), height: Math.round(metadata.height / 4) }) if (record.fields.difuminar) { pipeline = pipeline.blur(8) } await pipeline .composite([{ input: whiteOverlay, blend: 'over' }]) .webp({ quality: 85 }) .toFile(outputPath)
Skalowanie 1/4
Skaluje do 1/4. Zdjęcie 4032×3024 staje się 1008×756 — idealne na web, waga spada z ~3 MB do ~30 KB.
Warunkowe rozmycie
Stosowane tylko, gdy pole `difuminar` jest ustawione w Airtable. Sigma 8 rozmywa powiadomienia i dane osobowe na ekranie.
Jakość 85 vs 95
Niższa jakość niż przy zdjęciach profilowych, bo przy rozdzielczości 1/4 dodatkowy detal nie dodaje wartości. Oszczędza ~40% wagi na obraz.
Prawdziwy wynik: iPhone 14 Pro
To prawdziwe zdjęcia przetworzone przez pipeline. Front i tył, przed i po naprawie.




Ten sam pipeline, różne marki
Pipeline działa tak samo dla każdej marki i modelu. Tu zastosowany do Samsung Galaxy A51 i Xiaomi Redmi Note 9S.




Ten sam pipeline przetwarzania dla każdej marki. Zdjęcia są pobierane, skalowane, w razie potrzeby rozmywane i automatycznie eksportowane do WebP.
Skala
10,342
Przetworzone zdjęcia
Prawdziwe zdjęcia napraw skonwertowane do WebP
4
Kąty
Front przed/po + tył przed/po
1/4
Rozdzielczość
Przeskalowane do 25% oryginału pod web
Q85
Jakość WebP
Zoptymalizowana jakość zdjęć napraw
Krzywa wzrostu
Start w październiku 2024. Pierwsze miesiące to czysty momentum indeksacji. Po początkowym szczycie w styczniu ruch wypłaszczył się od lutego do czerwca — i to nie była sezonowość. To była restrukturyzacja: oryginalna wersja generowała strony krajowe i lokalne dla każdej kombinacji, ale było ich za dużo, a Google wyraźnie faworyzował intencję lokalną. Przekierowałem strony krajowe na lokalne odpowiedniki /sevilla, zostawiając w formacie krajowym tylko niszowe naprawy (np. /cambiar-bateria-iphone-11), gdzie specyfika waży więcej niż brak lokalizacji. Dopóki Google reindeksował nową strukturę, ruch stał w miejscu. Po konsolidacji wzrost ruszył znowu — szczyt we wrześniu 2025: 2193 kliknięcia.

| Miesiąc | Kliknięcia | Wyświetlenia | |
|---|---|---|---|
| Oct 2024 | 202 | 16,420 | Start |
| Nov 2024 | 748 | 69,054 | |
| Dec 2024 | 949 | 77,387 | |
| Jan 2025 | 1,277 | 110,836 | |
| Feb 2025 | 935 | 100,558 | Restrukturyzacja krajowe → lokalne |
| Mar 2025 | 1,191 | 118,826 | |
| Apr 2025 | 1,027 | 106,744 | |
| May 2025 | 936 | 97,137 | |
| Jun 2025 | 996 | 121,088 | |
| Jul 2025 | 1,611 | 150,927 | Po restrukturyzacji |
| Aug 2025 | 1,789 | 164,791 | |
| Sep 2025 | 2,193 | 164,440 | Szczyt · sprzedaż firmy |
Z 202 do 2193 kliknięć/miesiąc w 11 miesięcy. Plateau luty–czerwiec pokrywa się z restrukturyzacją URL z krajowych na lokalne — Google potrzebował czasu na reindeksację nowej architektury. Po konsolidacji ruch skoczył o 62% w jeden miesiąc (cze → lip). System dalej działa u nowego właściciela.
Kamienie milowe Google Search Console
Google świętuje progi ruchu odznakami. W 3 miesiące przeszliśmy z 1,2 tys. do 2 tys. kliknięć miesięcznie — ostatnia odznaka przyszła dokładnie przy domknięciu sprzedaży firmy.




Wyniki
Metryki skumulowane od startu (październik 2024 – luty 2026), bezpośrednio z Google Search Console:
19,388
Kliknięcia organiczne
17 miesięcy działania, paź 2024 → lut 2026
1.17%
Średni CTR
Przy 2,26 mln wyświetleń łącznie
4,084
URL-e w sitemapie
Tylko te, które przechodzą silnik decyzji DataForSEO
<1s
Czas ładowania strony
Astro SSG z minimalnym lazy JS + Cloudflare CDN
Ale te wyniki nie wzięły się znikąd. Punktem startu była strona na Squarespace z problemami technicznymi, które trzeba było rozwiązać, zanim dało się zbudować system programmatic.
Punkt startu
Strona firmy przez lata działała na Squarespace. Brak kontroli URL, brak tagów canonical, brak własnych przekierowań. Nadchodziła nie tylko zmiana platformy — potrójna migracja: platforma (Squarespace → Astro), domena (santifer.me → santiferirepair.es) i hosting (Squarespace → Vercel/Cloudflare). Pierwszy krok: udokumentować, co trzeba naprawić — 144-stronicowy audyt techniczny, zrobiony jako Final Master's Project programu Big SEO.


Squarespace serwował tę samą stronę pod 4 różnymi URL-ami (www, non-www, trailing slash, .html). Google widział 4 kopie każdej strony.
Audyt techniczny
Pierwszym krokiem był pełny audyt techniczny, zrobiony jako Final Master's Project programu Big SEO. 144 strony dokumentujące każdy aspekt techniczny serwisu: od baseline ruchu po ostatni meta description.
23.1
Śr. pozycja
↓ Spadek
Widoczność SISTRIX
21/100
Lighthouse (mobile)
33/40
Elementy z błędami



838 zduplikowanych H1
Szablon Squarespace wstrzykiwał ukryte H1 na każdej stronie, duplikując główny nagłówek. Google widział dwa tytuły walczące o relevance.
1015 kanibalizacji
Strony konkurujące ze sobą o te same słowa kluczowe. Home, kategorie i modele wchodziły sobie w drogę w wynikach.
869 błędów structured data
Schema LocalBusiness nie trzymała się rekomendacji schema.org. Google nie mógł poprawnie zinterpretować informacji o firmie.
831 stron non-canonical
Squarespace serwował 4 URL-e na stronę bez przekierowania na canonical. GSC raportował je jako duplikaty bez canonical.
33 z 40 audytowanych aspektów technicznych miało błędy. Tylko 7 przeszło. Audyt nie tylko zdiagnozował problemy — stał się roadmapą całego projektu.


Dług techniczny
Brak tagów canonical
www vs non-www, z/bez trailing slash, z/bez .html. Ta sama strona, 4 URL-e. 831 stron non-canonical w GSC. Squarespace ustawiał canonical, ale nie przekierowywał.
Brak własnych przekierowań
Squarespace nie pozwala na własne 301. 266 historycznych URL-i zwracających 404 w GSC. Niemożliwe mapowanie starych URL-i na nową strukturę.
Brak kontroli slugów URL
Taksonomia biznesowa już istniała, ale Squarespace generował redundantne URL-e typu /reparar-iphone/reparar-iphone-x. 15 URL-i powyżej 115 znaków, 10 z wielkimi literami, słowo kluczowe powtórzone 3 razy.
Ryzyko duplicate content
Wykryto 1015 kanibalizacji. 79 stron z thin content. Warianty URL bez canonical wysyłały mylące sygnały do Google, rozwadniając autorytet domeny.



Migracja
Pełny crawl Screaming Frog
Crawl wykazał 838 stron z wieloma H1, 266 URL-i z 404 i 1015 kanibalizacji. Mapowanie dało 1009 reguł przekierowań.
Nowa struktura URL w Astro
Z ~80 stron do architektury 480+ stron zoptymalizowanej pod 156 000 miesięcznych wyszukiwań transakcyjnych. Czyste URL-e: /reparar-{device}/, /reparar-{brand}/{model}/.
Przekierowania 301 w vercel.json
Dedykowany projekt (servidor-redirecciones) wdrożony na Vercel wyłącznie do serwowania 301. 190 KB konfiguracji w jednym pliku.
Przekierowania wg intencji
Przekierowanie stron krajowych na lokalne. Przykład: /reparar-movil/reparar-samsung → /reparar-movil/samsung/sevilla.
Serwer przekierowań
Potrójna migracja (platforma, domena, hosting) wymagała planu ochrony autorytetu zgromadzonego na starej domenie. Rozwiązaniem był dedykowany projekt Vercel, którego jedynym celem było serwowanie 301. Haczyk zmiany domeny: Squarespace nie pozwalał przekierować homepage, co blokowało change of address w GSC. Podwójny hop HTTP→308→301 uniemożliwiał walidację. Naprawione w jedno popołudnie: Vercel Redirect Domain + Cloudflare Redirect Rules dla jednego bezpośredniego 301.
1,009
Reguły przekierowań
190 KB
vercel.json
4
Warstwy przekierowań
46
Commitów w 7 miesięcy
Model → model
/reparar-movil/reparar-samsung/reparar-samsung-galaxy-a12 → /reparar-movil/samsung/galaxy-a12. Clean URL, same intent.
Marka → marka + miasto
/reparar-movil/reparar-realme → /reparar-movil/realme/sevilla. The new structure added the city as a local signal.
Wildcard + catch-all
Każdy URL nie zmapowany w poprzednich warstwach przekierowuje na homepage. Zero 404 dla użytkowników i dla Google.
Cały projekt Vercel wyłącznie do przekierowań. 1009 reguł zmapowanych ręcznie, bo struktura URL Squarespace nie miała jednolitego wzorca.
Wdróż przekierowania przed zgłoszeniem zmiany adresu w Google Search Console. Nie po. Kolejność ma znaczenie.
Koszt migracji
Każda migracja ma koszt przejścia. Ponad 800 stron potrzebowało czasu na reindeksację, a kluczowe słowa chwilowo spadły — „reparar iphone sevilla” z top 2 na pozycję 6. To było oczekiwane: Google potrzebuje czasu na ponowną ocenę domeny po change of address. Odbicie przyszło.
100
Wydajność
92
Dostępność
96
Dobre praktyki
100
SEO

Z Lighthouse 21 na Squarespace do 100 na Astro. Z DA 8 do konkurencji na rynku, gdzie liderzy mają 100× więcej ruchu. Audyt techniczny udokumentował 33 problemy; migracja rozwiązała je wszystkie naraz.
Stack i narzędzia
Stack dobrano pod konkretną potrzebę: generowanie tysięcy stron statycznych z relacyjnego CMS, z minimalnym JS po stronie klienta. Astro było oczywistym wyborem pod czyste SSG. Airtable działał jako CMS, bo już był Business OS firmy — migracja na Supabase pod statyczny serwis nie miała sensu. DataForSEO wybrano za cenę i pokrycie hiszpańskich słów kluczowych.
Astro
SSG, 21 szablonów, minimalny lazy JS
Airtable
Headless CMS, 14 tabel, ~60 pól/tabelę

DataForSEO
Wolumeny wyszukiwań, pole „indexable”
Własny ERP
867 modeli, ceny, stock, zdjęcia, opinie
Cloudflare
CDN, cache edge, deploy
TypeScript
1677-liniowy schema.ts do mapowania
JSON-LD
6 typów structured data na stronę
Wnioski
Intencję użytkownika decyduje Google, nie Ty.
Chciałem rankować ogólnokrajowo. Google miał inne plany — odczytał wyszukiwania napraw jako silnie lokalne. Strony bez miasta zostały zmiażdżone przez te z Sewillą. Wniosek: zbuduj pełną infrastrukturę, ale niech dane GSC powiedzą, gdzie podwoić stawkę.
Silnik decyzji liczy się bardziej niż generator.
Wygenerowanie 10 000 stron jest trywialne. Decyzja, które indeksować na podstawie realnych danych DataForSEO — to oddziela pSEO z wynikami od farmy thin content. Ze wszystkich możliwych kombinacji tylko 4084 trafiło do sitemapy.
ERP jest moatem, nie szablon.
Każdy może postawić strony z AI. Nikt nie wygeneruje prawdziwych zdjęć before/after, zweryfikowanych opinii, podwójnych cen (oryginał i kompatybilne) oraz czasów realizacji z danych historycznych bez zintegrowanego ERP. Unikalna treść nie bierze się z copy — bierze się z danych.
Airtable skaluje się lepiej, niż się spodziewasz.
14 tabel, ~60 pól na tabelę, hierarchia 6 poziomów. Z retry i exponential backoff na API build zostaje stabilny. Sztuczka: cache’uj opinie i pomijaj zbędne wywołania. Dla jednoosobowego zespołu Airtable jako headless CMS po prostu działa.
Krajowe URL-e niszowe dają najlepszy CTR.
Format /cambiar-bateria-google-pixel-6a daje CTR 5,0% przy średniej pozycji 7,8. Te zapytania są tak konkretne, że mają prawie zerową konkurencję. Pojedynczy wolumen jest niski, ale pomnożony przez setki modeli szybko się sumuje.
Treść generowana bez danych produkcyjnych to thin content z lepszą gramatyką.
Różnica między pSEO, które działa, a farmą treści to nie szablon ani AI — tylko to, czy dane są realne. Ceny z ERP, prawdziwe zdjęcia napraw, zweryfikowane opinie. Ten wzorzec dotyczy każdej firmy z danymi operacyjnymi: e-commerce, marketplace’y, SaaS katalogowe.
Taksonomia biznesu JEST Twoją architekturą informacji — nie wymyślaj jej, zmapuj ją.
Nie projektowałem struktury URL od zera. Zmapowałem hierarchię, która już istniała w biznesie: typ → marka → model → naprawa → miasto. Business OS miał już tę taksonomię w Airtable. Serwis programmatic po prostu wystawił ją światu. Jeśli Twoja firma ma już wewnętrzną ontologię — użyj jej.
Co to pokazuje
Projekt systemu end-to-end
Od danych ERP do stron produkcyjnych — relacyjny CMS, pipeline budowy, silnik decyzji, optymalizacja crawl budget.
Automatyzacja skalująca się bez interwencji
Jedna osoba, 4730 stron, ponad 26 000 obrazów. System działał dalej po sprzedaży firmy.
Decyzje data-driven, nie na czuja
DataForSEO jako silnik indeksacji. Google Search Console jako pętla feedbacku. Każda decyzja oparta o realne metryki.
Pełna realizacja w realnym kontekście biznesowym
To nie projekt portfolio ani tutorial. To system produkcyjny, który napędzał realny ruch realnej firmy — i przyczynił się do jej sprzedaży.
Ten sam ERP zasila agenta AI
Dane Airtable generujące te ponad 4700 stron są też odpytywane przez Jacobo, omnichannelowego agenta AI obsługującego WhatsApp i telefon. To samo źródło prawdy, dwa kanały pozyskania.
Projektuję systemy, które zamieniają dane operacyjne w przewagę konkurencyjną.
To case study pokazuje wzorzec, który stosuję wielokrotnie: zmapuj ontologię biznesu, zbuduj pipeline data-to-deploy i mierz wszystko realnymi metrykami. Obecnie rozglądam się za rolami AI Product Manager i Solutions Architect — jeśli Twój zespół potrzebuje kogoś, kto myśli systemami i dowozi na produkcję, pogadajmy.
FAQ
Czy programmatic SEO to nie spam?
Tylko jeśli strony nie dodają wartości. Tutaj każda ma realne dane usługi: aktualne ceny (części oryginalne i kompatybilne), czas realizacji z danych historycznych, zdjęcia before/after z prawdziwych napraw i zweryfikowane opinie klientów. To nie wypełniacz z AI — to dane produkcyjne z ERP.
Czy to działa tylko w Sewilli?
Strony lokalne skupiają się na Sewilli, bo tam jest fizyczny punkt, a Google faworyzuje wyniki blisko użytkownika przy wyszukiwaniach napraw. Strony krajowe (format /cambiar-{part}-{brand}-{model}) działają bez limitu geograficznego i łapią niszowe zapytania w całej Hiszpanii.
Dlaczego nie treści generowane AI?
Bo moatem są realne dane. Ceny z ERP, zdjęcia z prawdziwych napraw, opinie od zweryfikowanych klientów. Strona z AI może brzmieć dobrze, ale nie stoi za nią dane produkcyjne. Blog korzystał z AI do pisania, w parze z NotebookLM do odcinka podcastu przy każdym artykule.
Czy Airtable skaluje się przy ponad 4700 stronach?
Tak, z zastrzeżeniami. 14 tabel i ~60 pól na tabelę dobrze działa z pipeline’em budowy (nie z zapytaniami real-time). Klucz: retry z exponential backoff na API oraz cache często używanych danych, jak opinie. Przy żywych zapytaniach i większej skali warto rozważyć alternatywy typu Supabase.
Jak utrzymujecie strony na bieżąco?
Gdy zmienia się cena lub dodawany jest model w ERP, dane synchronizują się do Airtable. Kolejny build regeneruje dotknięte strony. Nowe opinie propagują się automatycznie przez kaskadę rodzina–model. Zero ręcznej pracy nad treścią.
Dlaczego Astro zamiast Next.js?
Dla w pełni statycznego serwisu, gdzie treść zmienia się rzadko, Astro oddaje czysty HTML z minimalnym JavaScriptem — tylko interaktywne komponenty jak wyszukiwarka i karuzela, ładowane lazy. Strony ładują się poniżej sekundy, Core Web Vitals są dobre od razu, a deploy na Cloudflare CDN jest banalnie prosty.
Co dokładnie robi DataForSEO?
DataForSEO dostarcza realny wolumen wyszukiwań dla każdego słowa kluczowego. Wynik trafia do pola „indexable” w Airtable. Jeśli kombinacja urządzenie + naprawa + miasto nie ma wolumenu, strona powstaje, ale z tagiem noindex. To silnik decyzji, który chroni przed rozwadnianiem autorytetu domeny stronami, które Google i tak zignoruje.