Blog'a Dön

n8n ile Google Maps Lead Otomasyonu: Adım Adım Rehber

Ilyas Yıldırım
Ilyas Yıldırım
11 dk okuma

Evet, n8n ile Google Maps müşteri adayı toplama süreci otomatikleştirilebilir. Akış BasedOnB API üzerinden bir tarama işi başlatır, iş bitene kadar kontrollü aralıklarla durumu okur, bütün sonuç sayfalarını çeker ve işletmeleri Google Sheets ya da CRM'e aktarır.

Sağlam bir otomasyon yalnız ilk POST isteğinden oluşmaz. Aynı isteğin iki kez iş açmaması, durum kontrolünün sonsuza kadar sürmemesi, hata dallarının ayrılması ve sonuçların 500'er satırlık sayfalar halinde alınması gerekir. Aşağıdaki örnek, İstanbul'daki diş kliniklerini hedefleyen denetlenebilir bir akış kurar.

Hangi alanların gerçekten işe yaradığından emin değilseniz önce Google Maps müşteri listesi rehberine bakın. Buradaki akış, kategori, konum, hedef kayıt sayısı ve aktarılacak alanların önceden belirlendiğini varsayar.

n8n'i açmadan önce gerekenler

Şunları hazırlayın:

  • Dışarıya HTTPS isteği gönderebilen bir n8n kurulumu.
  • Tarama okuma ve yazma yetkili bir BasedOnB API anahtarı. Anahtar bdb_live_ ile başlar.
  • place_id gibi sabit bir dış kimliği saklayabilen Sheet, CRM listesi veya tablo.
  • Idempotency anahtarına dönüşecek kampanya ya da kaynak olay kimliği.
  • Net bir sorgu, ülke, il, şehir ve hedef kayıt sayısı.

API anahtarını panelde oluşturun ve n8n içinde Header Auth kimlik bilgisi olarak saklayın. Canlı anahtarı Edit Fields düğümüne, dışa aktarılan akış dosyasına, ekran görüntüsüne veya destek mesajına yapıştırmayın. Güncel adresler ve yanıt alanları BasedOnB API dokümanında bulunur.

Toplu işleri planlamadan önce sınırları bilin. Bir iş en fazla 10 sorgu taşıyabilir. Bir hesapta aynı anda en fazla 2 açık iş bulunabilir. Açık işlerin toplam hedefi 5.000 kaydı geçemez. pending, submitted ve running durumları açık iş sayılır. Bu sınırları görmezden gelen bir zamanlama sonunda 429 kapasite yanıtı alır.

Akışın kısa görünümü

Polling akışı şu sırayı izler:

  1. Schedule Trigger veya Webhook bir kampanya alır.
  2. Edit Fields isteği düzenler ve sabit idempotency anahtarını ekler.
  3. HTTP Request, POST /api/v1/scrapes isteğini gönderir.
  4. IF, statusCode alanını kontrol eder; başarılı yanıt tek öğeli polling durumuna çevrilir.
  5. Wait ve Edit Fields, durum dalındaki attempt değerini artırır.
  6. HTTP Request, GET /api/v1/scrapes/:id çağrısını yapar; Merge yanıtı durum öğesiyle birleştirir.
  7. Switch, HTTP hatalarını, done, failed, cancelled ve açık durumları ayırır.
  8. done dalı sonuç sayfalarını çeker ve önce statusCode alanını kontrol eder.
  9. Her sayfa bir kez ikiye ayrılır: body.results Split Out'a, tek kontrol öğesi body.page kontrolüne gider.
  10. Kontrol dalı sonraki cursor değerini bir kez ister ve yanıtı aynı iki dal noktasına döndürür.

Resmi HTTP Request düğümü rehberi kimlik doğrulama, header, sorgu parametresi ve yanıt ayarlarını anlatır. Wait düğümü rehberi ise süreli bekleme ve devam etme davranışını açıklar.

1. Sabit bir istek oluşturun

Tetikleyiciden sonra Edit Fields düğümü ekleyin. İstanbul örneği için alanlar şöyle olabilir:

{
  "query": "dental clinics",
  "country": "TR",
  "state": "TR.34",
  "city": "Istanbul",
  "target_leads": 250
}

query kategori veya arama ifadesidir. country, state ve city alanı bölgeyi belirler. target_leads, istenen işletme kaydı sayısıdır. Bu değer kullanılabilir krediye ve açık iş sınırlarına uymalıdır.

Ayrıca idempotency_key alanı ekleyin. Örneğin istanbul-dis-klinikleri-2026-08-parti-01 gibi saklanan bir kampanya kimliği kullanın. CRM kampanya kodu veya kaynak sistemdeki olay kimliği de uygundur. Şimdiki zamanı kullanmayın. n8n yeniden çalıştığında yeni bir zaman damgası üretirse sunucu bunu yeni istek sayabilir.

2. Tarama işini başlatın

HTTP Request düğümünü şöyle ayarlayın:

  • Method: POST
  • URL: https://www.basedonb.com/api/v1/scrapes
  • Authentication: Authorization: Bearer bdb_live_... gönderen Header Auth kimlik bilgisi
  • Header: Edit Fields içindeki değerden Idempotency-Key
  • Body Content Type: JSON
  • Body: yukarıdaki beş istek alanı
  • Options > Response > Include Response Headers and Status: açık
  • Options > Response > Never Error: açık
  • Options > Response > Response Format: JSON

Bu yanıt ayarları, n8n'in 2xx dışındaki yanıtları düğümü durdurmadan output olarak vermesini sağlar. Tam öğede statusCode, headers ve body bulunur. Önce $json.statusCode üzerinden dallanın. Yalnız 2xx yanıtı iş durumu mantığına devam etsin. Bu yanıt için Poll State adlı Edit Fields düğümünde job_id = {{$json.body.id}}, job_status = {{$json.body.status}} ve attempt = 0 alanlarını oluşturun. Diğer durum kodlarını ortak HTTP hata dalına gönderin.

Yeni iş çoğu zaman submitted döner. Hazır bir ortak sonuç varsa done da dönebilir. Bu nedenle 2xx kontrolünden sonra, beklemeden önce $json.body.status alanını okuyun.

Aynı idempotency anahtarı ve aynı gövde yeniden gönderildiğinde ilk iş döner. Aynı anahtarı başka şehir, sorgu veya hedef sayısıyla kullanmak çakışma üretir. Anahtarı ve istek gövdesini tek bir kayıt gibi saklayın.

3. Wait, IF ve deneme sınırıyla polling yapın

Başarılı POST sonrasında oluşturulan Poll State öğesini kullanın. job_status alanını şu yollara ayırın:

  • done: doğrudan sonuç adımına geçin.
  • failed veya cancelled: terminal hata dalına gidin.
  • pending, submitted veya running: Wait düğümüne geçin.

Wait için örneğin 15 saniye belirleyin. Beklemeden sonra Edit Fields ile job_id alanını koruyun ve attempt = {{$json.attempt + 1}} yapın. Bu tek durum öğesini iki kola bağlayın. Bir kol doğrudan Merge düğümünün Input 1 girişine gitsin. Diğer kol şu adresi çağırsın:

GET https://www.basedonb.com/api/v1/scrapes/{{$json.job_id}}

Aynı Header Auth kimlik bilgisini ve POST düğümündeki üç Response ayarını kullanın. Durum HTTP yanıtını Merge düğümünün Input 2 girişine bağlayın. Merge ayarını Mode: Combine ve Combine By: Position yapın. Böylece birleşen öğede job_id ve attempt, statusCode ve body yanında kalır. GET yanıtı sayacı silemez.

Merge sonrasında gövdeyi okumadan önce $json.statusCode alanını kontrol edin. 2xx dışındaki öğeleri ortak HTTP hata dalına gönderin. 2xx yanıtında Switch, $json.body.status alanını okuyarak done, failed, cancelled veya açık durum ayrımını yapsın. Açık durum dalındaki ayrı IF, Wait'e dönmeden önce $json.attempt sınırını kontrol etsin.

Wait'e dönmeden önce ikinci bir IF koyun. attempt belirlediğiniz sınıra ulaştığında polling'i durdurun ve iş kimliğiyle sorumlu kişiye bildirim gönderin. Örneğin 15 saniyelik 40 deneme, bu n8n çalışmasının sınırını belirler. Her işin on dakikada biteceğini vaat etmez. Deneme sınırında işi otomatik iptal etmeyin. Sunucudaki iş daha sonra tamamlanabilir.

failed ve cancelled dalları kesinlikle döngüye bağlanmamalıdır. Terminal durumu, iş kimliğini, kampanya kodunu ve varsa istek kimliğini kaydedin. Yeni iş açmak gerekiyorsa bunu hatalı girdiyi inceledikten sonra yapın.

4. Bütün sonuç sayfalarını alın

Sonuç adresini yalnız durum done olduktan sonra çağırın:

GET https://www.basedonb.com/api/v1/scrapes/{{$json.id}}/results

Sorgu parametresi limit değerini 500 yapın. Diğer HTTP Request düğümlerindeki gibi Include Response Headers and Status ile Never Error seçeneklerini açın ve Response Format olarak JSON seçin. Önce $json.statusCode alanını kontrol edin; 2xx dışındaki öğeler ortak hata dalına gitsin. Başarılı tam yanıt şu biçimdedir:

{
  "statusCode": 200,
  "body": {
    "id": "scrape-job-id",
    "status": "done",
    "results": [],
    "page": {
      "limit": 500,
      "next_cursor": "next-page-token",
      "has_more": true,
      "total": 1250
    }
  }
}

Başarılı sayfa yanıtını tek öğe olarak tutup iki kola bağlayın. Veri kolu body.results üzerinde Split Out çalıştırır, sonra satırları eşleyip upsert eder. Kontrol kolu Split Out üzerinden geçmez. Bu koldaki IF, $json.body.page.has_more alanını okur ve işletme başına değil sayfa başına bir kez çalışır.

Kontrol kolu true olduğunda Edit Fields ile job_id = {{$json.body.id}} ve cursor = {{$json.body.page.next_cursor}} oluşturun. Next Results adlı HTTP Request, aynı adresi limit=500 ve bu cursor ile, aynı Response ayarlarını kullanarak çağırsın. Yanıtını ilk sayfanın kullandığı statusCode kontrolüne ve iki kola ayrılma noktasına geri bağlayın. False dalı sayfalamayı bitirir. Bir sayfada en fazla 500 satır olduğundan 1.250 kayıt üç istek gerektirir.

total değerini ilk yanıttaki satır sayısı sanmayın. Kendi sayfa numaranızı üretmeyin. Sunucunun verdiği cursor değerini aynen izleyin. Her sayfayı bir sonraki isteği yapmadan önce hedefe yazmak, yarıda kalan akışı kurtarmayı kolaylaştırır.

5. Google Sheets veya CRM alanlarını eşleyin

Veri dalında body.results dizisini Split Out ile satırlara ayırın. Ardından Edit Fields düğümünde hedef şemayı açıkça kurun:

BasedOnB alanıHedef alan
place_idexternal_id
titlecompany_name
categorycategory
addressaddress
phonephone
websitewebsite
ratinggoogle_rating
reviews_countgoogle_review_count

Tekrar kontrolü için place_id kullanın. CRM'de doğrudan create yerine upsert seçin. Google Sheets'te önce bu kimliği arayın, varsa satırı güncelleyin, yoksa ekleyin. Sadece append kullanırsanız n8n çalışması tekrar oynatıldığında kopya satırlar oluşur.

Upsert kullanın ve her sayfa için iş kimliği ile cursor değerini saklayın. Tek öğeli kontrol dalı, veri dalı satırları yazarken sonraki sayfayı çekebilir. Mutlaka yazma bittikten sonra çekmek istiyorsanız hedef daldan tek bir sayfa tamamlandı sinyali üretip kontrol öğesini bununla bekletin. Sonraki sayfa IF düğümünü Split Out sonrasına bağlamayın; aksi halde aynı cursor her sonuç için çağrılır.

Aktarımdan sonra lead listesi kalite karnesi ile eksik alan, tekrar, tazelik ve kaynak kontrollerini yapabilirsiniz. Listeyi yapay zeka asistanına verecekseniz yapay zeka ile müşteri adayı bulma rehberi, hangi işi modelin hangi işi veri kaynağının yapması gerektiğini ayırır.

Sık görülen hatalar

Never Error açık olduğu için her HTTP düğümünde iş alanlarından önce $json.statusCode üzerinden dallanın. 2xx dışındaki yanıtlarda $json.body.error.code ve $json.body.error.details alanlarını inceleyin. Hata gövdesi bu amaçlı dalda kullanılabilir.

401 Unauthorized: anahtar eksik, bozuk veya iptal edilmiştir. n8n kimlik bilgisini kontrol edin. Anahtarı execution log içine yazdırmayın.

403 Forbidden: anahtar geçerlidir ancak gereken tarama yetkisi yoktur. Yalnız gereken okuma ve yazma yetkilerine sahip kimlik bilgisini kullanın.

402 Payment Required: hesapta kredi, abonelik veya ödeme işlemi gerekir. Akışı durdurun ve hesap sahibine bildirin.

409 Conflict: aynı idempotency anahtarı farklı gövdeyle kullanılmıştır. Saklanan anahtar ile gövdeyi karşılaştırın. Aynı anahtarı yalnız ilk gövdeyi geri yükledikten sonra yeniden deneyin; bilerek yeni bir iş açacaksanız yeni ve sabit bir anahtar kullanın.

429 Too Many Requests: $json.body.error.details.reason alanını inceleyin. too_many_open_scrapes, 2 açık işten birinin bitmesini beklemeniz demektir. open_leads_limit, beklemeniz veya yeni hedefi açık işlerin toplamı 5.000'i geçmeyecek biçimde azaltmanız demektir. reason yoksa bunu istek hızı sınırı sayın; Retry-After yanıt başlığını veya $json.body.error.details.retry_after_seconds değerini sınırlı bir Wait dalında kullanın. Hızlı döngü başlatmayın.

Boş sonuç sayfası: iş durumunu kontrol edin. İş hâlâ açıkken sonuç adresi boş sayfa döndürebilir. Sonuç isteği, durum kontrolünün yerine geçmez.

Daha geniş olay tabanlı akışlar için Zapier ve Make otomasyon rehberindeki ilkeleri de kullanabilirsiniz. İş kimliği, terminal durumlar ve tekrar güvenli yazma her araçta önemlidir.

Polling mi webhook mu?

Polling kurması ve izlemesi kolaydır. Tek seferlik işler, seyrek zamanlamalar ve API'yi yeni öğrenen ekipler için uygundur. Bedeli, tekrar eden durum çağrıları ve deneme sayısını taşıyan bir n8n çalışmasıdır.

Webhook, işler sık çalışıyorsa veya süreleri değişiyorsa daha iyi seçimdir. n8n tamamlanma olayını alır, imzayı doğrular ve yalnız o zaman sonuç sayfalama dalını başlatır. Yine de hata yönetimi, cursor sayfalaması ve upsert gerekir. Webhook yalnız bitiş bilgisinin nasıl geldiğini değiştirir.

Durum modelini anlamak için sınırlı polling ile başlayın. Tekrarlanan kontroller operasyon yüküne dönüştüğünde webhook'a geçin.

Sık Sorulan Sorular

n8n Google Maps müşteri adaylarını otomatik toplayabilir mi?

Evet. n8n, BasedOnB REST API üzerinden bir Google Maps işletme araması başlatabilir, iş sürerken bekleyebilir, bütün sonuç sayfalarını çekebilir ve satırları Google Sheets ya da CRM'e gönderebilir. API anahtarını iş akışı alanında değil n8n kimlik bilgisinde saklayın.

Bu iş akışı için hangi n8n düğümleri gerekir?

Tetikleyici, Edit Fields, HTTP Request, Wait, IF veya Switch, Merge, Split Out ve hedef sistem düğümünü kullanın. Merge, durum yanıtının yanında polling sayacını korur. Split Out yalnız veri dalında kalır, böylece sayfalama kontrol dalı tek öğe taşır.

Neden Idempotency-Key göndermeliyim?

Bu başlık, tekrarlanan POST isteğini güvenli yapar. Aynı anahtar ve aynı istek yeniden gönderildiğinde yeni iş açılmaz, ilk iş döner. Saat bilgisinden anahtar üretmek yerine sabit bir kampanya veya kaynak olay kimliği saklayın.

n8n iş durumunu ne sıklıkla kontrol etmeli?

Durum isteklerinin arasına Wait düğümü koyun ve en yüksek deneme sayısı belirleyin. Sabit 10 ile 20 saniyelik aralık pratik bir başlangıçtır, ancak bitiş süresi sözü değildir. Sınıra gelince sonsuza kadar sorgulamak yerine akışı durdurup sorumlu kişiye haber verin.

500'den fazla sonucu nasıl alırım?

Bir istekte en fazla 500 satır alın. Tam HTTP yanıtındaki body.page.has_more ve body.page.next_cursor alanlarını okuyun. Sayfalamayı tek öğeli kontrol dalında tutun ve has_more false olana kadar sonuç adresini cursor ile yeniden çağırın.

n8n içinde polling mi webhook mu kullanmalıyım?

Polling ilk akış ve seyrek işler için daha kolaydır. Sık ya da uzun süren işler için imzalı webhook daha uygundur, çünkü n8n tekrar tekrar durum isteği atmak yerine tamamlanma olayını bekler. İki yöntemde de sonuçlar cursor ile sayfalanır.

İş failed veya cancelled olursa ne yapılmalı?

failed ve cancelled durumlarını terminal kabul edin. Sonuç istemeyin ve bu dalı yeniden Wait düğümüne bağlamayın. İş kimliğini ve durumu kaydedin, sorumlu kişiye bildirin ve yeni istek açma kararını ayrıca verin.

İlk işi küçük ve kurtarılabilir tutun

Tek kategori, tek şehir ve gözle kontrol edebileceğiniz bir hedef tabloyla başlayın. Yeni BasedOnB hesabına kart gerekmeden tek seferlik 50 dışa aktarma kredisi gelir. Hedefi büyütmeden önce alan eşlemesini, idempotency anahtarını, hata dalını ve upsert kuralını bu kayıtlarla doğrulayın.

Kimlik bilgisini oluşturun, sınırlı ilk akışı çalıştırın ve her aktarılmış satırın yanında iş kimliğini saklayın. Bu küçük kaynak bilgisi, otomasyonu denetlemeyi ve gerektiğinde onarmayı kolaylaştırır.