RSelenium İle JavaScript İşlemleri

ExecuteScript İle Fonksiyon / Değişken Kontrolü

Web sitesi, uygulamalar ve servis entegrasyonu süreçlerinde önemli konulardan biri ilgili izleme kodlarının hangi sayfalarda var olup olmadığının anlaşılmasıdır. Özellike farklı ekipler tarafında yönetilen ve birçok servisin bir arada ele alındığı süreçlerde sayfa temelinde kontroller de karmaşıklalabilmekte.

AA

Hemen hemen pek çok servis alan adı ve/ya alt alan adları aracılığı ile sayfaları yayınlamakta. Sayfa düzenlemelerinde de doğrudan sayfa alanı veya global olarak tüm sayfaları etkileyen kod eklemeleri mümkün. Diğer yandan, Google Tag Manager gibi etiket yönetim araçlarının da devreye girmesi ile birlikte var olan kodların kontrolleri de ayrı bir süreç haline gelebilmekte.

Aşağıdaki gibi bir örnek akışımız olsun.

flowchart TD 1(Typeform) 2[Alt Domain 1] 3[Alt Domain 2] 6[Blog] 5(ClickFunnel) 4(EventBrite) 7[Domain] 8[(Google Analytics)] 9[(Facebook Pixel)] 10[[Google Tag Manager]] 1 & 4 & 5 & 6 & 7 -.-> 8 & 9 2 & 3 --> 10 10 --> 8 & 9

Servisler alt alan adı veya doğudan kendi sundukları alan adları ile yönetilebilmekte. Bu servislerin çoğu doğrudan Google Analytics ve Facebook Pixel desteği sunmakta. Farklı alan anlarında Google Tag Manager, alt alan adları için oğrudan kurulumlar yapıldığını varsayalım. Bu durumda, var olan bir kurulumun kontrolü için izlenebilecek birkaç yol mevcut;

  • Tüm sayfaların tek tek kaynak kodlarının kontrol edilmesi,
  • Tüm sayfaların ağ hareketleinin izlenmesi,
  • Facebook Pixel ve/veya Google Tag Assistant ile kontrol
  • Çerez kontrolü
  • Analitik servisi üzerinden izlenen sayfaların kontrolü
  • JavaScript değişkenlerini kontrol edilmesi
  • 3. parti servisler ve uygulamalar (GA Checker, vb.)

JavaScript değişkenleri ve çerez kullanımıda console üzerinden işlemler gerçekleştirilebilir. Ancak, elbette bu yazı bağlamında sürecin nasıl otomatize edilebileceğine odaklanacağım.

Facebook Pixel IDs
Facebook Pixel IDs

Facebook Pixel kurulu sayfalarda işlemler _fbq fonksiyonu ve çerezi ile ilişkili olarak fbq olayları (sayfa görüntüleme, lead, vb.) çerçevesinde ele alınır. Google Analytics ise _ga çerezini gaData nesnesini temel alır. Bu sayede sayfada işlemekte olan mülk bilgilerine ulaşabiliriz.

// Facebook
Object.keys(_fbq.instance.pixelsByID)

// Google Analytics
Object.keys(gaData)

Birazdan bu bilgileri kullanacağız. Öncelikle servisler konusuna geri dönelim. Eğer safa yönetimi ve testler bir liste altında derleniyor ise doğrudan bu sayfa listesini kullanabilirsiniz. Diğer durumda, taranacak sayfaların kontrolü için maalesef bir mesai harcamak gerekecek. Ben örnek olması açısından Google Analytics'in tüm sayfaları taradığını varsayacağım. Dolayısıyla, sayfa verilerini ya API aracılığı ile ya da sunulan dışa aktarma seçenekleri ile sürece dahil edeceğim.

Kod kontrollerinde de sayfaları Google Analytics üzerinden çektiğim için ayrıca Object.keys(gaData) kontrolü yapmama gerek kalmıyor. Ancak, harici bir liste ya da sitemap dosyaları üzerinden işlem gerçekleştirecekseniz elbette Google Analytics kontrolünü de sürece dahil edebilirsiniz.

library(readxl)
PageURL <- read_xlsx(path = '20201001-20210407.xlsx', sheet = 2)
checkList <- PageURL$Page

RSelenium ve JavaScript İşlemleri

Bir sonraki aşama bu sayfaların tek tek kontrol edilmesi. Bu amaçla RSelenium paketini kullanacağım1. RSelenium, Selenium yeteneklerini R aracılğı ile kullanılabilir hale getiren kapsamlı test ve otomasyon paketlerden biri. Selenium ise web uygulamalarını test etmek amacıyla geliştirilmiş olan, farklı platform ve tarayıcı desteği sunan açık kaynaklı ve ücretsiz bir test aracıdır2.

Aşağıdaki örnek Selenium temelideki temel fonksiyonları da ayrıca görebilirsiniz.

driver <- rsDriver(port = 4567L, browser = c("firefox"), version = 'latest', verbose = TRUE, check = TRUE)
remote_driver <- driver[["client"]]
remote_driver$open()

getFBIDs <- function(url){
  url <- if(str_detect(url, "https://")) url else paste0("https://", url)
  remote_driver$navigate(url)
  remote_driver$executeScript("
    var pageURL = window.location.href;
    var fbqID = (typeof fbq === 'function')
      ? Object.keys(_fbq.instance.pixelsByID)
      : false;
    return { pageURL, fbqID }
  ")
}

Pixels <- lapply(checkList, getFBIDs)
crawledData <- as.data.frame(do.call(rbind, Pixels))

remote_driver$closeServer()
remote_driver$close()

Öncelikle, rsDriver ile bir tarayıcı seçiyor ve port tanımlıyoruz. Sonraki ileteceğimiz her komut bu belirlediğimiz arayıcı aracılığı ile gerçekleştirilecek. Komutun uygulanmasının ardından belirtilen sürüm bilgilerine bağlı olarak tarayıcının indirme ve yapılandırma işlemleri gerçekleştirilecek. İşlemin tamamlanmasının ardından tarayıcı aktif hale gelerek yönlendirmeleri beklemeye başlayacak3 4.

Firefox
Firefox

driver değerini kontrol ederseniz Selenium'a ait client ve server içeriklerine ulaşabilirsiniz. Sonraki işlemleri client aracılığı ile gerçekleştireceğimiz için remote_driver ile bu değeri alıyoruz.

$client
  browserName                                   id
1     firefox 4a44cbb3-7052-9b40-b5ec-f2cf281bf091

$server
PROCESS 'filed1931848b908.sh', running, pid 72794.

remote_driver$navigate(url) ile bir adres bilgisi tarayıcıya iletmemiz ilgili sayfanın görüntülenmesi ve sonraki komutlar için hazır hale gelmesi için yeterli. Bu işlem aynı sekme üzerinden yürütülecektir. Selenium çoklu sekme oluşturma ve izleme olanağı da sunmakta5. Ancak, bu işlemi doğru bir şekilde uygulayamadığım için şimdilik es geçiyorum. Bir çözüme ulaştığımda bu yazıya ayrıca ekleme yapacağım.

URL işlemlerinin yanı sıra, Selenium temelinde daha pek çok işlem yapılabilir (değer okuma, tıklama, scroll, form doldurma, vb.). Biz şimsilik JavaScript işlemlerine odaklanalım ve executeScript ile örnek işleme devam edelim.

  remote_driver$executeScript("alert('Hello World!')")

executeScript içerisinde temel JavaScript kuralları ve elbette seçtiğimiz tarayıcıya bağlı olarak JavaScript komutları oluşturabilir ve sayfada uygulanmasını sağlayabiliriz6. Ancak, bu işlem ile birlikte gerçekleşen duruma ait verilere ihtiyacımız var ise return kullanmayı unutmamamız gerekir.

  remote_driver$executeScript("
    var pageURL = window.location.href;
    var fbqID = (typeof fbq === 'function')
      ? Object.keys(_fbq.instance.pixelsByID)
      : false;
    return { pageURL, fbqID }
  ")

Yukarıdaki kod parçacığı ilgili sayfadaki Facebook Pixel ID'lerini ve sayfa URL'ini dönmekte. Sayfa URL'ini almamın nedeni, listede yer alan sayfaların çalışmıyor ve/veya farklı sayfalara yönlenebiliyor olma düşüncesi. Elbette bu işlem öncesinde httr ve/veya rcurl ile ilgili URL'lerin status kontrolünü gerçekleştirmek daha doğru bir adım olacaktır.

Cross-domain işlemlerde alan adları da Google Analytics sayfa alanına (aksi belirtilmediği sürece) yer alacaktır.

Eğer sayfada bir veya daha fazla Facebook Pixel kodu mevcut ise her bir Pixel ID ilgili URL ile ilişkili olarak bize liste elemanı olarak iletilecektir. Ardından, listeyi elbette data frame haline getirerek daha okunaklı kılmamız uygun olacaktır.

Tüm bu süreç sonunda aşağıdakine benzer bir sonuç elde ederiz.

                                              fbqID                                                                            pageURL
1 100023405678901, 111112334456778, 123123123123123 https://www.clickfunnels.com/?aff_sub=domain_redirect&utm_campaign=domain_redirect
2                                   123123123123123 https://domain.com/
3                                   123123123123123 https://blog.domain.com/page-v-1

Görüldüğü üzere, ilk satır bize checkList[1]'in artık kullanımda olmadığını göstermekte. Dolayısıyla, bize iletilen Pixel ID'ler de clickfunnels'e ait ve bu nedenle bir sonraki aşamaya bu tür alanları temizleyerek geçmemiz gerekmekte.

İlgili kodu tek parça olarak RSelenium-JavaScript-Variable-Check.R sayfasında görebilirsiniz.