Shopify mağazası yavaşladığında ilk suçlanan yer genelde yanlış yerdir. Shopify altyapısı global bir CDN üzerinde çalışır ve sunucu yanıt süresi (TTFB) çoğu Türkiye mağazasında zaten kabul edilebilir seviyededir. Yavaşlığın kaynağı neredeyse her zaman bu altyapının üzerine eklenen katmandır: kurulan uygulamalar, temaya elle yapıştırılmış script'ler, sıkıştırılmamış hero görselleri, üç farklı font ailesi ve Liquid tarafında kontrolsüz büyümüş döngüler.
Bu rehber, satış dili olmadan, gerçekten uygulayabileceğiniz sırayla ilerliyor: önce doğru ölçme, sonra tanı, sonra müdahale. Sonunda tema teslim ederken kullanabileceğiniz bir kontrol listesi var.
Önce doğru ölçün: Lighthouse ile gerçek kullanıcı verisi aynı şey değil
Hız optimizasyonunda en sık yapılan hata, tek bir Lighthouse taramasına bakıp karar vermektir. Lighthouse bir laboratuvar testidir: tek bir simüle edilmiş ziyaret, sabit bir cihaz profili, yapay bir ağ kısıtı. Gerçek kullanıcılarınız ise farklı telefonlarda, farklı bağlantılarda ve farklı davranışlarla geziyor. İki veri türünü ayırmadan yapılan optimizasyon, skoru yükseltip gerçek deneyimi aynı bırakabilir.
Core Web Vitals eşikleri (güncel)
Google, sayfa deneyimini üç metrikle ölçüyor ve değerlendirmeyi gerçek kullanıcı verisinin 75. persentilinde yapıyor. Yani ziyaretlerin %75'inin eşiği geçmesi gerekiyor; ortalama değil.
| Metrik | Ne ölçer | İyi | Geliştirilmeli | Kötü |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | En büyük içerik öğesinin görünme süresi | 2,5 sn altı | 2,5 - 4,0 sn | 4,0 sn üstü |
| INP (Interaction to Next Paint) | Etkileşime verilen yanıt süresi | 200 ms altı | 200 - 500 ms | 500 ms üstü |
| CLS (Cumulative Layout Shift) | Beklenmedik yerleşim kaymaları | 0,1 altı | 0,1 - 0,25 | 0,25 üstü |
INP, eski FID metriğinin yerini aldı ve Shopify mağazaları için en zorlayıcı olanı genelde budur. Çünkü FID sadece ilk etkileşimin gecikmesini ölçüyordu; INP ise ziyaret boyunca yapılan tüm etkileşimlerin en kötüsüne yakın bir değeri raporlar. Sepete ekle butonu, varyant seçici, mega menü, filtre paneli, sepet çekmecesi... Hepsi INP'yi doğrudan etkiler.
Shopify'ın kendi ölçüm araçları
Shopify yönetim panelinde iki ayrı şey var ve bunlar karıştırılıyor:
- Hız skoru (Speed score): Lighthouse tabanlı bir laboratuvar skorudur. Ana sayfanızın, son yedi günde en çok ziyaret edilen ürün sayfanızın ve en çok ziyaret edilen koleksiyon sayfanızın Lighthouse performans skorlarının ağırlıklı ortalamasıdır ve günde bir kez (09:00 UTC civarı) yeniden hesaplanır. Yani bugün yaptığınız iyileştirmeyi burada yarın görürsünüz.
- Web Performance (Web performansı) paneli: Gerçek ziyaretçilerden toplanan alan verisidir. LCP, INP ve CLS için günlük ve 28 günlük P75 değerlerini gösterir. Online Store > Themes üstündeki özet bandından veya Analytics > Reports altından ulaşılır.
Karar verirken alan verisine bakın, hata ayıklarken Lighthouse'a. Bir de Google Search Console'un Core Web Vitals raporu var; o da 28 günlük kayan pencere kullandığı için yaptığınız düzeltmenin etkisini görmek haftalar alabilir. Bu gecikmeyi bilmeden "düzelttim ama değişmedi" paniğine kapılmayın.
Ölçüm yaparken sık yapılan 4 hata
- Mağaza yöneticisi olarak giriş yapmışken test etmek. Önizleme çubuğu, tema düzenleyici script'leri ve yönetici oturumu ek yük getirir. Her zaman gizli sekmede ve çıkış yapmış halde ölçün.
- Şifre korumalı mağazayı ölçmek. Şifre sayfası gerçek şablonunuz değildir; sonuç yanıltıcı derecede iyi çıkar.
- Tek sayfa ölçmek. Ana sayfa genelde en ağır sayfadır ama gelirin çoğu ürün ve koleksiyon sayfalarından gelir. Üçünü de ayrı ölçün.
- Sadece masaüstünde ölçmek. Türkiye e-ticaret trafiğinin ağırlığı mobilde. Mobil Lighthouse profili masaüstünden çok daha katıdır ve gerçek durumu daha iyi yansıtır.
Shopify mağazasını yavaşlatan gerçek nedenler
1. Uygulama script birikimi ve kaldırılan uygulamaların artık kodu
Bu, listenin bir numarasıdır ve genelde en az konuşulanıdır. Shopify'da bir uygulamanın temaya kod enjekte etmesinin birkaç yolu var ve kaldırma davranışları birbirinden farklı:
- App embed block (uygulama gömme bloğu): Uygulamaya bağlıdır. Uygulamayı kaldırdığınızda veya bloğu kapattığınızda tema tarafındaki çıktısı da gider. Modern ve temiz yöntem budur.
- Tema dosyalarına elle yapıştırılan kod: Kurulum sırasında
theme.liquidiçine eklenen <script> satırları, kopyalanan snippet'ler, section dosyaları. Uygulamayı kaldırdığınızda bunlar temada kalır. Artık var olmayan bir servise istek atan, hiçbir işe yaramayan ama yine de indirilip çalıştırılan ölü kod haline gelirler. - Uygulamanın yüklediği asset dosyaları:
assets/klasöründe kalan JS/CSS dosyaları. Referansları silinmezse yüklenmeye devam eder.
Bir mağazada iki yıl boyunca denenip vazgeçilmiş 8-10 uygulama olması hiç şaşırtıcı değil. Sohbet widget'ları, sosyal kanıt bildirimleri, sayfa oluşturucular, geri sayım sayaçları, kur çevirici... Her biri arkasında birkaç satır bırakır. Bunları temizlemek genelde tek başına en yüksek getirili işlemdir çünkü hem indirilen bayt sayısını hem de ana thread'de çalışan JavaScript miktarını azaltır. INP'yi doğrudan iyileştirir.
2. Hero görselinin boyutu ve formatı
Ana sayfanın LCP elemanı neredeyse her zaman hero görselidir. Tasarımcıdan gelen 4000 piksel genişliğinde, 3 MB'lık bir PNG doğrudan yüklendiğinde mobilde LCP 5-6 saniyeye çıkabilir. Shopify CDN, tarayıcı desteklediğinde görselleri otomatik olarak WebP formatında sunar; ancak boyutu siz belirtmezseniz orijinal genişlik gönderilir. Yani "Shopify zaten optimize ediyor" cümlesi yarım doğrudur.
3. Üçüncü parti pixel'ler ve etiket yöneticileri
Meta Pixel, TikTok Pixel, Google Ads, GA4, ısı haritası araçları, e-posta pazarlama script'leri... Bunlar tek tek küçük görünür ama toplamda ana thread'i uzun süre meşgul eden "long task"lar üretir. Google Tag Manager üzerinden yüklenen her etiket ayrı bir istek ve ayrı bir yürütme demektir.
Shopify'ın buna cevabı Web Pixels API'dir. Web pixel eklentileri ve özel (custom) pixel'ler, mağaza sayfasından yalıtılmış bir sandbox içinde, ana thread dışında çalışır; storefront'un DOM'una, çerezlerine veya değişkenlerine erişemez. Bu, izleme kodunun sayfayı bloklamasını mimari olarak engeller. Bir izleme aracını hem theme.liquid'e elle eklemiş hem de pixel olarak tanımlamış olmak ise çift sayım ve gereksiz yük demektir; sık rastlanan bir durumdur, kontrol edin.
4. Özel font yüklemesi
Üç ayrı font ailesi, her birinin 4 ağırlığı ve italik varyantları... Bu, sadece fontlar için 8-12 ayrı dosya indirmek demektir. Dahası, font-display ayarlanmamışsa tarayıcı font inene kadar metni gizler (FOIT) ve LCP metin bloğuysa doğrudan gecikir. Shopify'ın kendi font kütüphanesindeki fontlar bunu otomatik yönetir; harici yüklenen özel fontlarda sorumluluk sizdedir.
5. Slider, carousel ve jQuery bağımlılıkları
Eski temalarda hâlâ jQuery + Slick Slider kombinasyonu görülür. Sadece ana sayfadaki bir banner döngüsü için 90 KB'lık jQuery indirmek anlamsızdır. Ayrıca carousel'ler CLS'nin klasik kaynağıdır: slide'lar yüklendikçe konteyner yüksekliği değişir ve sayfa zıplar. Modern alternatifler (CSS scroll-snap, hafif Web Component tabanlı slider'lar) çoğu senaryoyu kütüphanesiz çözer.
6. Liquid tarafında gereksiz döngü ve metafield sorguları
Bu, sunucu tarafındaki maliyettir ve TTFB'yi doğrudan büyütür. Tipik hatalar:
- İç içe döngüler: Bir koleksiyon döngüsünün içinde her ürün için varyantları ve her varyant için metafield'ları dolaşmak. Liquid render süresi katlanarak büyür.
- Mega menüde tüm koleksiyonları dolaşmak:
{% for collection in collections %}ile menü kurmak, mağaza büyüdükçe her sayfada ödediğiniz bir vergi haline gelir. Menü yapısınılinklistsüzerinden kurun. - Döngü içinde
all_productsaraması: Ürünü handle ile tek tek çekmek, döngü içinde en pahalı işlemlerden biridir. - Sayfalama yokluğu: Koleksiyon döngüleri sayfalama olmadan sınırlı sayıda ürün döndürür ve sınıra dayandığınızda hem eksik veri hem gereksiz yük alırsınız.
{% paginate %}kullanın. - Hâlâ
{% include %}kullanmak: Kullanımdan kaldırıldı.{% render %}değişken kapsamını izole eder, hem daha güvenli hem daha performanslıdır.
7. Büyük DOM ve gizlenmiş içerik
Mobilde görünmeyen ama HTML'de var olan mega menüler, tüm filtre seçenekleri, gizli varyant tabloları... display:none ile gizlemek tarayıcının o düğümleri ayrıştırmasını engellemez. Binlerce DOM düğümü hem ilk render'ı hem de her etkileşimdeki stil hesaplamasını yavaşlatır, yani INP'yi bozar.
Adım adım iyileştirme
Adım 1: Uygulama envanteri çıkarın ve artık kodu temizleyin
- Temayı yedekleyin. Online Store > Themes > Duplicate. Bu adımı atlamayın; geri dönüş yolunuz budur.
- Yüklü uygulamaları listeleyin ve her biri için "bu ay bana ne kazandırdı?" sorusunu sorun. Cevabı olmayanı kaldırın.
- Kaldırdıktan sonra tema kodunda arama yapın:
theme.liquid,layout/,sections/,snippets/içinde uygulama adını, alan adını veya<scriptifadesini aratın. - Bulduğunuz bloğu silmeden önce yorum satırına alın, mağazayı gezin, sepete ürün ekleyin, ödeme adımına kadar gidin. Sorun yoksa silin.
assets/klasöründe hiçbir yerden referans verilmeyen JS/CSS dosyalarını tespit edin ve kaldırın.- Tema düzenleyicide App embeds sekmesini açın; kapalı ama duran gömme bloklarını temizleyin.
Not: Yalnızca kaldırdığınızdan emin olduğunuz uygulamaların kodunu silin. Hâlâ aktif bir uygulamanın snippet'ini silmek sepet veya ödeme akışını bozabilir.
Adım 2: Görselleri Liquid ile doğru üretin
Temaya hiçbir zaman ham cdn.shopify.com adresi yapıştırmayın. Görseli image_url filtresinden geçirin ve işaretlemeyi image_tag üretsin. image_tag, genişlik/yükseklik özniteliklerini otomatik ekler; bu tek başına görsel kaynaklı CLS'nin büyük bölümünü çözer.
{{ product.featured_image
| image_url: width: 1200
| image_tag:
widths: '300, 600, 900, 1200',
sizes: '(max-width: 768px) 100vw, 50vw',
loading: 'lazy' }}widths parametresi srcset'i, sizes ise tarayıcıya görselin sayfada gerçekte kaç piksel geniş görüneceğini söyler. sizes yanlışsa srcset işe yaramaz: tarayıcı yine gereğinden büyük dosyayı indirir. Bu detay çoğu temada atlanır.
Adım 3: LCP elemanını bulun ve önceliklendirin
Lighthouse raporunda "Largest Contentful Paint element" satırı size hangi öğenin LCP olduğunu söyler. Bulduktan sonra kural basit:
- LCP görseline asla
loading="lazy"vermeyin.loading: 'eager'vefetchpriority: 'high'kullanın. - Ekranın altındaki her görsele
loading: 'lazy'verin. Shopify tarafında bir kolaylık var: şablonun ilk üç section'ından sonrakiimage_tagçağrıları, siz belirtmediyseniz otomatik olarakloading="lazy"alır. - Section'ın konumuna göre karar vermek isterseniz
section.index,section.index0vesection.locationözelliklerini kullanabilirsiniz. Böylece aynı section farklı konumlarda doğru davranır.
Kritik bir asset'i öne çekmek gerekiyorsa preload_tag filtresi var. Girdisi asset_url, global_asset_url veya shopify_asset_url filtrelerinden gelmelidir:
{{ 'critical.css' | asset_url | preload_tag: as: 'style' }}Preload'u dikkatli kullanın. Her şeyi preload etmek hiçbir şeyi preload etmemekle aynı kapıya çıkar; bant genişliği yarışı yaratıp asıl LCP kaynağını geciktirebilir. Sayfa başına bir, en fazla iki kritik kaynak.
Adım 4: Render'ı bloklayan CSS ve JS'i azaltın
Hedef, ilk ekranı çizmek için gereken minimum CSS'i satır içi vermek, gerisini ertelemektir. Pratikte Shopify temalarında uygulanabilir olanlar:
- Tek bir dev
theme.cssyerine, section bazlı{% stylesheet %}blokları kullanmak. - Tüm <script> etiketlerine
defereklemek. Analitik ve widget script'leri içinasyncyeterlidir. - Sadece bir sayfada gereken JS'i her sayfada yüklememek. Ürün sayfası galeri kodu ana sayfada işe yaramaz.
- Sepet, filtre ve arama gibi kısmi güncellemeler için tüm sayfayı yeniden yüklemek yerine Section Rendering API'yi kullanmak.
Adım 5: Font stratejisini sadeleştirin
- Font ailesi sayısını ikiye indirin: bir başlık, bir gövde. Mümkünse tek aile.
- Ağırlık sayısını sınırlayın. 400 ve 700 çoğu tasarımı taşır. Tarayıcının "faux bold" üretmesi, ekstra dosya indirmekten daha ucuzdur.
- Özel font kullanıyorsanız yalnızca woff2 sunun ve
font-display: swapverin. Shopify font ayarlarını kullanıyorsanızfont_facefiltresi bunu destekler:{{ settings.body_font | font_face: font_display: 'swap' }} - Fallback font ile web font arasındaki metrik farkını azaltın (
size-adjust, benzer x-height'lı yedek font). Aksi halde swap anında düzen kayar ve CLS artar.
Adım 6: INP'yi düşürün
LCP'yi düzelttikten sonra çoğu mağazanın takıldığı yer INP olur. Yaklaşım şudur:
- Uzun görevleri (long task) bulun. Chrome DevTools > Performance panelinde 50 ms üzeri her blok adaydır.
- Etkileşim anında ağır iş yapmayın. "Sepete ekle"ye basıldığında aynı anda üç ayrı analitik olayı gönderiliyorsa bunları etkileşim sonrasına erteleyin.
- Olay dinleyicilerini tek tek yüzlerce elemana bağlamak yerine olay delegasyonu kullanın.
- Filtre panellerinde
inputolayına debounce uygulayın. - DOM boyutunu küçültün. Site içi arama sonuçlarını tek seferde yüzlerce ürünle basmak yerine sayfalama veya sanal liste kullanın. Arama deneyimini modülle çözüyorsanız, sonuçların istemci tarafında değil sunucuda süzülmesi INP açısından belirgin fark yaratır; site içi arama modülü gibi çözümlerde bu davranışı sormaya değer.
Adım 7: Liquid'i temizleyin
Tema düzenleyicide bir section'ın yavaş olduğuna dair uyarı görüyorsanız, o section'daki döngüleri inceleyin. Pratik kurallar:
- Aynı veriyi döngü içinde tekrar tekrar hesaplamayın; döngü dışında bir değişkene atayın.
{% liquid %}bloğu ile art arda gelen mantığı toplayın; okunabilirlik dışında render maliyetini de sadeleştirir.- Metafield'ları yalnızca gerçekten gösterdiğiniz yerde okuyun. Ürün kartında kullanmadığınız 6 metafield'ı çekmeyin.
- Koşullu bloklarda önce ucuz kontrolü yapın:
{% if section.settings.show_badges %}kontrolü, pahalı döngünün dışında olsun.
Tema teslim kontrol listesi
| Kontrol | Neden |
|---|---|
| LCP görseli eager + fetchpriority high | LCP |
| Ekran altı tüm görseller lazy | LCP, bant genişliği |
| Tüm <img> etiketlerinde width/height veya aspect-ratio | CLS |
| srcset ve doğru sizes değeri | Mobil veri, LCP |
| En fazla 2 font ailesi, woff2, font-display swap | LCP, CLS |
| Tüm script'lerde defer veya async | Render bloklama, INP |
| Kaldırılmış uygulamaların artık kodu temizlendi | Her şey |
| İzleme kodları Web Pixels üzerinden | INP, ana thread |
| Mega menü linklist ile, tüm koleksiyon döngüsü yok | TTFB |
| Koleksiyon döngülerinde paginate var | TTFB |
| include yerine render kullanılıyor | Bakım, render süresi |
| Duyuru çubuğu, popup ve sticky bar yer kaplamayı önceden rezerve ediyor | CLS |
| Gizli sekmede, çıkış yapmış halde, mobil profilde ölçüldü | Doğru ölçüm |
Yapmamanız gerekenler
"Hız artırıcı" uygulama kurmak. Bir performans sorununu, ana thread'de çalışan başka bir JavaScript ekleyerek çözmek çelişkilidir. Bu uygulamaların yaptığı işlerin çoğu (lazy loading, minify, preload) tema tarafında kod ile ücretsiz ve daha kontrollü yapılabilir.
Sadece skoru kovalamak. Lighthouse skorunu 90'a çıkarıp, gerçek kullanıcı verisinde LCP'nin 3,8 saniyede kalması mümkündür. Skor bir teşhis aracıdır, hedef değildir.
Her şeyi lazy load etmek. Hero görselini lazy yapmak LCP'yi belirgin şekilde kötüleştirir. Lazy loading ekran altı için vardır.
Yedeksiz kod silmek. Uygulama artık kodu temizliği, ödeme akışını bozma potansiyeli olan tek adımdır. Yedek + kademeli silme + test şart.
Gerçekçi beklenti
Uygulama temizliği, görsel düzeni ve font sadeleştirmesi çoğu mağazada en büyük kazancı verir ve genelde birkaç saatlik bir iştir. Bunun ötesindeki kazanç (kritik CSS, INP mikro optimizasyonları, section bazlı JS bölme) tema mimarisine dokunmayı gerektirir ve tema satın alındığı gibi kullanılıyorsa sınırlıdır. Tema seçiminin baştan doğru yapılması, sonradan yapılan optimizasyondan daha etkilidir; Shopify Tema Mağazası'ndaki temaların üç ana şablonda belirli bir Lighthouse eşiğini geçmesi beklenir, ancak bu eşik yalnızca bir taban çizgisidir ve uygulama yüklendikçe hızla erir.
Mevcut temayı optimize etmek yerine sıfırdan performans odaklı kurulum tercih edilecekse, tema mimarisi ve uygulama seçimi baştan birlikte planlanmalıdır; Shopify mağaza kurulumu ve tasarımı tarafında bu iki kararı ayrı ayrı vermek en sık yapılan hatadır.
Ölçün, tek seferde tek değişiklik yapın, 28 günlük alan verisinin oturmasını bekleyin. Hız optimizasyonu bir proje değil, sürekli bir bakım disiplinidir. Sorularınız için: destek@stools.digital