Schéma propojení Pipedrive CRM s Google Ads přes Google Apps Script bez Zapieru — 0 Kč/měs

Problém: Offline konverze jsou zlatý grál B2B PPCčka. Bez nich bidding algoritmus v Google Ads plave v surových leadech — od tipicích “přečtu si za týden” až po “podepisuju rámcovku” — a všechno váží stejně. Většina “standardních” cest, jak dostat CRM data zpět do Google Ads, je přitom placená (Zapier, Make, LeadsBridge, HubSpot connector).

Tenhle článek je o tom, jak jsem pro jednoho klienta propojil Pipedrive → Google Sheet → Google Ads bez jediného SaaS třetí strany. Celé to běží v Google infrastruktuře, zdarma, a kód za mě napsala AI během 45 minut. Ukážu architekturu, praktické kroky i kde nás to chytlo za nohu.

Obsah

1. Proč offline konverze, když už měřím form submity?

Typický B2B lead proces vypadá takhle:

  1. Uživatel klikne na reklamu (Google Ads přiřadí GCLID — Google Click ID).
  2. Vyplní formulář → vznikne Lead v CRM (Pipedrive, HubSpot…).
  3. Obchodník ho kvalifikuje → MQL (Marketing Qualified Lead).
  4. Po hovoru → SQL (Sales Qualified Lead).
  5. Časem → uzavřený obchod v hodnotě třeba 250 000 Kč.

Pokud do Google Ads posíláš jen krok 2 (form submit), algoritmus se učí optimalizovat množství leadů — ne jejich kvalitu. A to je zásadní rozdíl: leady za 50 Kč, z nichž se obchoduje jeden ze 40, vs. leady za 500 Kč, kde se obchoduje jeden ze 4. Druhá cesta je obvykle dramaticky levnější na akvizici zákazníka, ale bez offline dat to algoritmus nikdy nezjistí.

Řešením jsou offline konverze. Do Google Ads se vrací jen kliky, které prošly kvalifikací v CRM — ideálně s hodnotou (fakturační potenciál, pipeline value, fixní proxy). Bidding se přepne z “pošli mi víc leadů” na “pošli mi leady, které se reálně obchodují”.

2. Co se standardně platí

Než jsem se do toho pustil, měl jsem dvě cesty před sebou:

NástrojTypická cenaCo umí
Zapier19–69 USD/měs dle operacíPipedrive trigger → Sheet/Ads action
Make.com (Integromat)9–29 EUR/měsStejné, levnější při vyšším objemu
LeadsBridge22 USD/měs+CRM → Ad platform specialista
HubSpot ↔ Google Ads nativev rámci HubSpot Marketing Pro (890 EUR/měs)Pouze HubSpot klienti
CustomerLabs49 USD/měs+Server-side CDP přístup

Na stole reálně máš 500–1 500 Kč měsíčně jen za to, že “něco přenáší řádek z Pipedrive do Google Ads”. Klientů, co to chtějí, mám víc. Ten účet narůstá.

A tady vstupuje otázka, která mě začala žrát: proč to platím, když veškerou logiku zvládne 50 řádků JavaScriptu v Google Apps Scriptu — zdarma, bez infrastruktury, bez vendor lock-inu?

3. Architektura, kterou jsem nasadil

Tři komponenty, žádná mimo ekosystém Google a Pipedrive:

  1. Pipedrive — GCLID se ukládá do custom fieldu u Leadu (typicky jako hidden field ve formuláři, který se plní přes GTM z gclid query parametru nebo cookie _gcl_aw).
  2. Google Apps Script (konkrétně Google Ads Script, který sedí přímo uvnitř Google Ads účtu) — zadarmo, má vlastní UrlFetchApp pro HTTP volání, SpreadsheetApp pro Sheets, a umí scheduled triggers (každé ráno v 6:00).
  3. Google Sheet — dva listy. První Vcera se každý den přepisuje čerstvými daty (debug pohled). Druhý Append se nikdy nemaže — historie všeho, co kdy skript zpracoval. Audit trail zdarma.

Výsledný CSV/sheet se pak buď nahrává ručně do Google Ads (Tools → Conversions → Uploads), nebo si na to pustíš další scheduled script, který ho posílá přes Ads API automaticky. Já jsem zvolil ruční upload — klient má rád manuální kontrolu před zápisem do Adsů, a upřímně je to jen jedno kliknutí týdně.

4. Co se reálně napsalo

Tady je zkrácená anatomie klíčové funkce (bez tokenů a konkrétních field hashů — ty jsou v reálném skriptu v konstantách nahoře):

				
					function syncPipedriveLeads() {
  const API_URL = `https://${SUBDOMAIN}.pipedrive.com/api/v1/leads`;
  const sheet = SpreadsheetApp.openById(SHEET_ID);

  // 1. Pipedrive paginated pull — včerejšek
  const yesterday = new Date(Date.now() - 86400000);
  const leads = fetchPipedriveLeads(API_URL, yesterday);

  // 2. Filtr — jen s GCLID
  const withGclid = leads
    .filter(l => l.custom_fields[GCLID_FIELD_HASH])
    .map(l => ({
      gclid: l.custom_fields[GCLID_FIELD_HASH],
      conversion_time: new Date(l.add_time).toISOString(),
      conversion_name: 'MQL_offline_qualified_lead',
      conversion_value: 1000,
      currency: 'CZK'
    }));

  // 3. Zápis: list "Vcera" přepíše, "Append" naappenduje
  writeReplace(sheet.getSheetByName('Vcera'), withGclid);
  writeAppend(sheet.getSheetByName('Append'), withGclid);

  Logger.log(`Zpracováno ${withGclid.length} leadů`);
}
				
			

Pomocných funkcí je cca 40 dalších řádků — paginace API, error handling, hash lookup custom fieldu. Celý skript má pod 150 řádků včetně komentářů. Spustí se každý den v 6:00 ráno automaticky. Nic víc se o něj nestarám.

5. Kde nás to chytlo za nohu (poctivá část)

Nic nešlo napoprvé čistě. Dvě konkrétní pasti, na které narazíš i ty:

A. add_time vs. conversion_time → data v roce 1970

První verze posílala do Sheetu sloupec add_time_utc, ale měla jsem v něm “1970-01-01 00:00:42”. Klasický Unix epoch 0 — znak, že do new Date() přichází něco nečitelného (nejčastěji null nebo prázdný řetězec).

Pipedrive vrací add_time ve formátu "2026-04-18 14:22:11" (bez T, bez Z), což JavaScriptový Date konstruktor v Apps Scriptu parsuje podle locale prostředí serveru — a když prohrab, je to UTC, ale musí se to ošetřit explicitně:

				
					// Pipedrive vrací "YYYY-MM-DD HH:mm:ss" v UTC
const isoTime = leadAddTime.replace(' ', 'T') + 'Z';
const jsDate = new Date(isoTime);
				
			

Tohle je ta kvalifikovaná práce, kterou AI samotná neudělá — musíš vidět v datech, že něco nesedí, a vědět, že “conversion time v roce 1970 je vždycky parsing error, nikdy ne vstup”.

B. Custom field hash, ne název

Pipedrive neumožňuje dotazovat custom fields podle názvu “GCLID”. Každý field má 40znakový hash jako klíč (5d8f…e3b2). Najdeš ho jen přes GET /leadFields:

				
					const fields = UrlFetchApp.fetch(`${API_URL}/leadFields?api_token=${TOKEN}`);
const gclidField = JSON.parse(fields).data.find(f => f.name === 'GCLID');
const GCLID_HASH = gclidField.key;  // tohle si ulož do Sheet konstant
				
			

Hash se nemění, takže stačí jednou. Ale musíš o něm vědět.

6. Iterace 2: 90denní backfill

Jakmile skript chodil na denní bázi, potřebovali jsme historický import — 90 dní zpětně, abychom do Google Ads nalili kvalifikované leady i za dobu, kdy tohle ještě neběželo. Jednorázová modifikace:

  • Místo yesterday vzít rozsah now - 90 days.
  • Paginace přes Pipedrive API (cursor-based, ?start=0&limit=100).
  • Rate limit ošetřit sleepem 100 ms mezi requesty (Pipedrive povoluje ~100 req/10s).
  • Vypsat rovnou do Sheetu připraveného pro Google Ads offline conversion import (formát Google Click ID, Conversion Name, Conversion Time, Conversion Value, Conversion Currency).

Hotovo za dalších 10 minut. Spustíš ručně, stáhneš CSV, uploadneš do Google Ads, zavřeš.

7. Iterace 3 (plánovaná): Enhanced Conversions for Leads

Zatím posíláme jen GCLID. Další logický krok jsou Enhanced Conversions for Leads — k GCLID přibalíš hashovaný e-mail a telefon, aby se konverze přiřadila i v případě, že GCLID vypršel nebo se ztratil (typicky mobile → desktop handoff).

Rozšíření skriptu:

				
					// SHA-256 email lowercased + trimmed
const hashedEmail = hashSha256(lead.email.trim().toLowerCase());
// E.164 phone hashed
const hashedPhone = hashSha256(normalizePhoneE164(lead.phone));
				
			

V Apps Scriptu musíš SHA-256 implementovat přes Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, ...) — nativní podpora tam je, jen s tím musíš umět pracovat.

8. Co mi to reálně přineslo

ParametrZapier/Make cestaMoje Apps Script cesta
Měsíční cena500–1 500 Kč0 Kč
Setup time30–60 min45 min (včetně ladění)
Vendor lock-inAnoNe
Audit trailPlacený addonZdarma (list Append)
CustomizaceOmezená (no-code logika)Plný JavaScript
Škálovatelnost na další klientyExtra účet / seatCopy-paste + změna konstant

Nejdůležitější čísla ale nejsou tyhle. Jsou dvě jiná:

  • Kód napsala AI. Neseděla jsem nad dokumentací Pipedrive API. Řekla jsem “máme subdoménu, máme token, GCLID je custom field, data do Sheetu s dvěma listy — piš” a dostala funkční draft. Druhý prompt byl “conversion_time ukazuje rok 1970, oprav to”. Třetí prompt byl “udělej verzi pro 90denní backfill”. Hotovo.
  • Moje role se změnila. Nenapsala jsem ani řádek. Ale bez toho, že vím, co přesně chci, jak vypadá offline conversion import formát Google Ads, co je GCLID a proč musí být audit trail, by to AI neuhádla. Expertíza neleží v kódu — leží v zadání.

9. Co to znamená pro PPCčkaře v roce 2026

Ještě před rokem by mi nasazení takového trackeru trvalo den. Dnes 45 minut. Za dalších šest měsíců to nejspíš AI udělá z jediného promptu “propoj mi Pipedrive s Ads, GCLID je tam jako text” a sama si dohledá hash, sama napíše error handling, sama to nasadí.

A to je důvod, proč vnímám třetí strany typu Zapier jako přechodný mezičlánek. Existovaly proto, že kód byl drahý — specialista na integrace stál tisíce měsíčně, no-code nástroj 500 Kč. Když se cena kódu blíží nule (= cena AI asistence), mezičlánek přestává dávat smysl.

Pro nás PPCčkaře to znamená tři posuny:

  1. Prodejní argument se mění. Místo “zapojíme Zapier, bude vás to stát 29 USD/měs” teď říkám “napíšu skript, bude to vaše, nulové náklady, plná kontrola”. Klienti to slyší rádi. Zvlášť ti, kdo už někdy platili za obskurní SaaS, který zanikl, nebo zdražil o 200 %.
  2. Hranice mezi PPCčkařem a analytikem se rozostřuje. Nejsem developer, ale umím přečíst 150 řádků JavaScriptu a vědět, že je pošahané posílat 1970 do Google Ads. Kdo to neumí a spoléhá výhradně na no-code, má konkurenční nevýhodu, protože neumí klientovi postavit přesně to, co potřebuje.
  3. Cena se přesouvá z licencí na know-how. Vše, co jsem popsal, stojí 0 Kč měsíčně. Moje práce na tom stojí jako předtím (nebo víc, protože prostřednictvím AI jsem schopný nasadit víc klientům za stejný čas). Klient už neplatí za “software, který to propojuje”, platí za “člověka, který ví, co a proč se má propojit”.

10. Kdy tohle nedělat

Pro férovost: Apps Script cesta není vždy správná.

  • Team >20 lidí, který to musí spravovat bez tebe: no-code nástroj s GUI je méně bolestivý než skript, který rozumí jen autor.
  • Velmi vysoký objem (>100 000 leadů/den): Apps Script má execution limity (6 min per run pro free Google účty, 30 min pro Workspace). Pro extrémní objem skript rozdělíš na batche nebo přejdeš na dedikovanou Python/Node službu.
  • Komplexní větvení logiky (if Pipedrive status = X AND source = Y AND age > 30 → do kanálu A, jinak B): vizuální flow v Make je čitelnější pro klienta, který chce do workflow nakukovat sám.

Ale pro 80 % use-casů “dostaň mi data z CRM do Google Ads”? Apps Script + AI = nejčistší cesta, jakou dnes znám.

Závěr

Zapier jsem nezrušil. Klienti, kde už běží a funguje, ať tam je. Ale u žádného nového napojení už ho nenavrhuju. Mám lepší kartu — vím přesně, co chci, a mám asistenta, který to do rána napíše.

Pokud řešíš offline konverze z Pipedrive (nebo HubSpotu, Raynetu, čehokoli jiného s veřejným API) a dosud platíš měsíční poplatek za přenos řádků, dej mi vědět. Ukážu ti to na tvých datech a za půl dne to běží na tvé infrastruktuře, zdarma, navždy.

Platíš Zapieru a víš, že to jde jinak?

Napiš mi. Ukážu ti cestu, která běží na tvé infrastruktuře, zdarma, navždy. Reálná data, půl dne, žádné SaaS.

Technické detaily, které jsem vynechal (pro zvědavé)

  • Proč Google Ads Script, a ne Google Apps Script standalone? Google Ads Script běží v kontextu konkrétního Ads účtu, má přímý přístup k AdsApp (pro případnou pozdější automatizaci = upload offline conversions přes API), a scheduled triggery řeší nativně v Ads UI. Plus — klient už tam má login, nemusíš řešit separate Workspace.
  • Proč ne Google Cloud Function / Cloud Run? Funguje stejně, ale přidáváš infrastrukturu, GCP projekt, billing account, IAM. U 99 % klientů zbytečně. Apps Script je “file, trigger, done”.
  • Proč listy Vcera + Append, a ne všechno do jednoho? Debug. Vcera je svižný čitelný pohled “co přišlo dneska”. Append je historie pro audit (kdyby Google Ads hlásil “tenhle GCLID neznáme”, hledám ho v Appendu a hned vidím, kdy jsme ho posílali). Oddělení = mentální čistota.
  • Conversion value 1000 CZK je proxy, ne skutečná hodnota dealu. Pro Smart Bidding je důležitější relativní váha mezi různými konverzemi než absolutní čísla. Pokud hodnotu znáš (ACV, LTV proxy), posílej ji. Pokud ne, fixed proxy na úrovni MQL je stále lepší než nic.

Petr Svoboda

Jsem PPC specialista na volné noze a krom kampaní vám pomohu i s webovou analytikou, SEO, UX a celkovým konceptem vašeho marketingu.

petr@marketak-ze-severu.cz | +420 774 051 339