Digital Marketing Tools and Technologies
Paid Advertising and PPC Management
Data Analysis and Reporting in Marketing

LinkedIn Ads to Google Sheets: B2B Firmographic Reporting (2026)

Adela
April 28, 2026
LinkedIn Ads to Google Sheets for B2B: ABM Attribution by Firmographic 2026

If you run LinkedIn Ads, you're running a B2B channel. That changes what reporting should look like. Most "LinkedIn Ads to Google Sheets" guides walk you through exporting a CSV of impressions and clicks. That misses the point: on LinkedIn, what moves the budget conversation isn't CTR — it's which job seniority, company size, or industry produced the leads that closed.

This guide takes the data flow as a means, not the end. Three methods to get LinkedIn data into Sheets (manual CSV, Apps Script, scheduled connector), the LinkedIn-specific quirks at each layer (60-day token rotation, app review for Lead Gen scopes, API versioning), and then — the part the rest of the internet skips — the two B2B reports you should be building: an ABM account-level engagement tracker and a firmographic lead-gen waterfall.

For the CRM-side analysis that picks up after the lead hits HubSpot, see our HubSpot to Google Sheets for RevOps guide. This post is about the acquisition side: getting LinkedIn ad data into a form you can slice by firmographic and join to deal data. For creative testing cadence on a different paid channel, see our Meta Ads to Google Sheets guide; for analytics data integrity, the GA4 to Google Sheets guide; for SEO trust, the Search Console to Google Sheets guide.

What LinkedIn exposes that Google and Meta don't

Before the methods, the data. LinkedIn's Marketing API exposes firmographic breakdowns that don't exist on any other paid channel:

  • MEMBER_INDUSTRY — the LinkedIn industry of the impression recipient
  • MEMBER_JOB_FUNCTION — broad role (Marketing, Engineering, Sales, Finance, etc.)
  • MEMBER_SENIORITY — IC, Manager, Director, VP, CXO
  • MEMBER_COMPANY_SIZE — bucketed (1–10, 11–50, 51–200, 201–500, 501–1000, 1001–5000, 5001–10000, 10001+)
  • MEMBER_REGION_V2 — region of the member
  • MEMBER_COUNTRY_V2 — country
  • COMPANY — the named company at account level (when matched)

These aren't available on Google Ads or Meta in the same fidelity. The B2B insight that LinkedIn unlocks is that you can answer "Which VP-level marketers at 200–1000-person SaaS companies cost us the most per qualified lead?" The Campaign Manager UI lets you ask one breakdown at a time. Sheets — with proper extraction — lets you cross-tabulate them and join to CRM.

If you don't pull these breakdown dimensions, you can't build the firmographic waterfall. The default columns in Campaign Manager don't show them; you have to add them in the column picker (UI), specify them as a pivot parameter (API), or select them in the connector field picker. Each method section below explains how.

Method 1: Manual CSV export from Campaign Manager

For one-off audits and quarterly board decks. Fast, free, useless for recurring B2B reporting because next week's data isn't in the export.

Setup: in LinkedIn Campaign Manager, select the ad account, pick the level (Account, Campaign Group, Campaign, or Ad), set date range, click Export, pick a report type:

  • Performance — impressions, clicks, spend, conversions (campaign-level, no firmographic breakdown by default)
  • Audiencethis is the B2B-relevant one: breakdowns by industry, job function, seniority, company size, region
  • Lead Gen Form — separate report for form submits with full form response fields
  • Conversion — for Insight Tag conversion data
  • Content — for organic content performance (not ads)

For B2B reporting you need two exports per week minimum: the Audience report (firmographic breakdowns) and the Lead Gen Form report (form submits). Then you stitch them together in Sheets manually by campaign ID.

LinkedIn-specific gotchas at this layer:

  • Audience breakdowns are one dimension at a time. The UI export lets you pick Industry OR Seniority OR Company Size — not all three at once. Cross-tabulating "industry × seniority × company size" requires the API or connector route.
  • Lead Gen form responses don't include the firmographic dimensions. The Lead Gen export gives you what the user typed in the form; the Audience export gives you the LinkedIn firmographic data. Joining them means matching on submitted email + campaign ID, which is fragile.
  • Lead Gen Forms have a separate column structure per form. If campaign A and campaign B use different forms with different fields, the CSV columns differ. Stitching multi-campaign Lead Gen data in one sheet means a column reconciliation pass.
  • Date ranges over 90 days deliver by email instead of immediate download. The email arrives 5–30 minutes later, fragmenting the workflow.

Fits when: quarterly board snapshot, agency RFP one-off, attribution audit.

Doesn't fit when: weekly multi-account reporting, ABM list matching, anything you need to slice by more than one firmographic dimension at a time.

Method 2: Google Apps Script + LinkedIn Marketing API

The path for an internal B2B team that wants daily refresh, multi-pivot firmographic data, and ABM list matching — without subscribing to a connector. Setup: 2–4 hours including the LinkedIn app review wait. Maintenance: yours forever.

Step 1 — Create a LinkedIn Developer App. Go to developers.linkedin.com, create an app, request Marketing Developer Platform access. The scopes you need for B2B reporting:

  • r_ads — read ad accounts, campaigns, ads structure
  • r_ads_reporting — read analytics (impressions, clicks, conversions, breakdowns)
  • r_ads_leadgen_automation — read Lead Gen form responses
  • r_organization_social — read your company page activity (optional, for organic context)

The r_ads_leadgen_automation scope requires LinkedIn app review before it works in production. Typical wait: 3–10 business days. The other ads scopes are typically auto-approved for Marketing Developer Platform partners but still gated behind app review.

Step 2 — OAuth 2.0 flow. Tokens are 60-day lifetime. Build a refresh token flow if you want long-term automation, or accept that someone re-authenticates every 60 days.

Step 3 — Apps Script that pulls firmographic breakdown. Paste into Extensions → Apps Script in your Sheet:

function pullLinkedInFirmographic() {
 const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';
 const SPONSORED_ACCOUNT = 'urn:li:sponsoredAccount:1234567890';
 const VERSION = '202604'; // check the LinkedIn API versioning page for current

 // pivot=MEMBER_SENIORITY gives you cost/clicks/conversions broken out by seniority level
 // change pivot to MEMBER_INDUSTRY, MEMBER_COMPANY_SIZE, MEMBER_JOB_FUNCTION as needed
 const url = 'https://api.linkedin.com/rest/adAnalytics' +
   '?q=analytics' +
   '&pivot=MEMBER_SENIORITY' +
   '&dateRange=(start:(year:2026,month:4,day:1),end:(year:2026,month:4,day:30))' +
   '&accounts=List(' + encodeURIComponent(SPONSORED_ACCOUNT) + ')' +
   '&fields=externalWebsiteConversions,impressions,clicks,costInUsd,leadGenerationMailContactInfoShares,pivotValue';

 const response = UrlFetchApp.fetch(url, {
   headers: {
     'Authorization': 'Bearer ' + ACCESS_TOKEN,
     'LinkedIn-Version': VERSION,
     'X-Restli-Protocol-Version': '2.0.0'
   },
   muteHttpExceptions: true
 });

 const data = JSON.parse(response.getContentText());
 const sheet = SpreadsheetApp.getActiveSheet();
 sheet.clear();
 sheet.appendRow(['Seniority','Impressions','Clicks','Spend USD','Conversions','Lead Form Submits']);

 (data.elements || []).forEach(row => {
   sheet.appendRow([
     row.pivotValue,
     row.impressions,
     row.clicks,
     row.costInUsd,
     row.externalWebsiteConversions,
     row.leadGenerationMailContactInfoShares
   ]);
 });
}

Step 4 — Schedule. Apps Script → Triggers → Add Trigger → run daily at 6 AM. Your firmographic breakdown refreshes before standup.

LinkedIn-specific gotchas at the API layer:

  • LinkedIn-Version header is mandatory and changes every quarter. Forgetting to update it gives a 400. Track the LinkedIn API versioning page.
  • The r_ads_leadgen_automation scope requires app review. Without it, your Lead Gen form responses come back empty even if the API call succeeds.
  • Single-pivot only per call. The pivot parameter takes one value. To get "industry × seniority", you need two pulls and an outer join in Sheets — or use pivots (plural) on the v202403+ versions for cross-tabulation.
  • Rate limits are tier-based. Standard apps: a few hundred analytics calls per day. Marketing Developer Platform partners get higher limits. Hitting 429 mid-pull leaves your sheet half-populated.
  • Lead Gen form responses are a separate endpoint (/rest/leadFormResponses), not part of adAnalytics. Pulling form submits + firmographic + cost data in one report means three API calls and a merge.

For setting up the underlying ad account permissions correctly before any of this works, see our LinkedIn Ads setup guide for agencies.

Skip the LinkedIn API maintenance

60-day token rotation, app review, single-pivot calls, three endpoints to merge. Dataslayer handles all of it, plus 50+ other connectors (HubSpot, Salesforce, Google Ads, Meta) in the same workbook.

Try Dataslayer Free

Method 3: Scheduled connector (no-code)

The path for B2B teams or agencies with multiple LinkedIn ad accounts (typical for a portfolio of clients or a parent-company-plus-subsidiaries setup), or for teams who need cross-pivot breakdowns without writing the merge logic.

Dataslayer connects LinkedIn Ads to Google Sheets in under 10 minutes. From Google Sheets: Extensions → Add-ons → Get add-ons → install Dataslayer. Then Extensions → Dataslayer → Launch, pick LinkedIn Ads, authenticate, pick accounts, pick dimensions, pick metrics, set date range, click Run.

Why a connector wins specifically for B2B LinkedIn work:

  • Multi-account at one query. Agencies tracking 5–20 client ad accounts pull them into one workbook with an account column. The connector batches API calls respecting per-account rate limits.
  • Cross-pivot dimension picker. Pick Industry, Seniority, and Company Size in the same query — the connector handles the multi-pivot merge under the hood. The Dataslayer LinkedIn Ads connector exposes the full breakdown surface from the Marketing API.
  • Lead Gen form responses integrated. Form-level questions appear in the same query as ad performance data, joined automatically on campaign + form ID. No manual stitching.
  • Insight Tag conversions surfaced. externalWebsiteConversions is exposed as a standard metric — you don't have to remember the field name from the API docs.
  • Scope authorization handled. The OAuth flow prompts for r_ads, r_ads_reporting, and r_ads_leadgen_automation together, so Lead Gen data works on first run instead of after a re-auth.

Pricing: Free for 1 connector and 1 user. Starter $35/month annual covers 3 connectors and 1 destination. Advanced $115/month adds hourly schedule, AI Insights, and MCP integration for Claude/ChatGPT (ask Claude "what changed in our LinkedIn CPL by seniority this week?" and it queries live). Pro $345/month covers 100+ accounts per connector. See dataslayer.ai/pricing.

The LinkedIn gotcha NO method solves: the LinkedIn Conversions API (CAPI) for server-to-server conversion uploads is a write API — none of the read-side tools cover it. If you need to send conversions back to LinkedIn for offline attribution, you're using the Conversions API directly or a CDP that wraps it. Read methods (CSV, Apps Script, connector) handle pulling data out of LinkedIn.

The 2 B2B dashboards worth building

Once data flows to Sheets, here are the two reports that change how B2B marketing makes budget decisions. Neither is something the LinkedIn UI shows, and both require the firmographic breakdown + Lead Gen response pulls.

Dashboard 1: ABM account-level engagement tracker

The question: of the 200 named accounts on our ABM target list, which ones are seeing our ads, who at those accounts is clicking, and what's the funnel from impression to closed-won?

Columns to pull from LinkedIn:

  • Campaign ID, Campaign Name (filter to ABM-targeted campaigns)
  • Impressions, Clicks, Spend, externalWebsiteConversions (campaign-level)
  • Pivot by COMPANY (the named-account-level breakdown) — gives you impressions/clicks per target company
  • Pivot by MEMBER_JOB_TITLE within each company (which roles inside the account are seeing/clicking)

Columns to pull from your CRM (HubSpot, Salesforce):

  • Account name (matched to LinkedIn COMPANY)
  • Lifecycle stage (Lead, MQL, SQL, Opportunity, Customer)
  • First touch source = LinkedIn, lifecycle date stamps

Calculations in Sheets:

  • Account engagement score: Impressions × 1 + Clicks × 10 + Form Submits × 100 per company — flags warming accounts
  • Account-level CPL: LinkedIn spend on that company / leads from that company (when company column on CRM matches)
  • Time to first MQL after first impression: MQL_date - first_impression_date per account (where MQL came in via LinkedIn)

Pivot layout:

  • Rows: target account name (top 50 by engagement score)
  • Columns: impressions, clicks, form submits, leads to CRM, lifecycle stage, days since first impression
  • Conditional formatting: highlight accounts where engagement score doubled week-over-week

What this surfaces that LinkedIn UI doesn't:

  • "Acme Corp has seen 4,200 impressions across 17 employees, 8 clicks, 0 form submits" → ad fatigue at this account, or wrong creative for their stage
  • "Globex moved from 0 to 32 clicks in 2 weeks across 9 different VPs" → buying committee activation; tell sales now
  • "We've spent $1,200 on Initech impressions over 60 days with no Lead Gen submit" → kill or rotate creative

Dashboard 2: Firmographic lead-gen waterfall

The question: of the form submits we got last quarter, which job seniority / company size / industry combinations actually converted to closed-won — and what was the cost per closed-won by segment?

Columns to pull from LinkedIn:

  • Lead Gen Form responses (one row per submit): submitted email, submitted company, submitted job title, campaign ID, form ID, submit timestamp
  • Pivot by MEMBER_SENIORITY on adAnalytics: impressions/clicks/spend/conversions per seniority bucket
  • Pivot by MEMBER_COMPANY_SIZE: same metrics per company-size bucket
  • Pivot by MEMBER_INDUSTRY: same metrics per industry

Columns to pull from your CRM:

  • Contact email (matched to Lead Gen submitted email)
  • Lifecycle stage progression: MQL date, SQL date, Customer date
  • Deal amount and stage (joined via primary contact)

Calculations in Sheets:

  • MQL conversion rate by seniority: % of Lead Gen submits where seniority = VP that hit MQL within 30 days
  • SQL conversion rate by company size: of submits where company size = 200–1000, what % hit SQL
  • Closed-won rate by industry: % of Lead Gen submits in SaaS industry that became Customer
  • Cost per closed-won by segment: LinkedIn spend on that segment / number of closed-wons from that segment

Pivot layout:

  • Rows: seniority × company size combinations (e.g., "VP at 200–1000-person co", "Manager at 1000–5000-person co")
  • Columns: submits, % to MQL, % to SQL, % to Customer, cost per customer
  • Sort by cost per customer ascending

What this answers that the QBR can't without this report:

  • VPs at 200–1000-person companies have a 31% MQL→Customer rate vs Directors at the same size at 11% — shift budget toward VP-targeted campaigns
  • SaaS industry: cost per customer is $4,200 vs Manufacturing: $14,000 — the LinkedIn budget is going to the wrong vertical
  • The CXO seniority bucket has the lowest CPL but the lowest closed-won rate — they fill the form, never buy. Stop bidding for CXO impressions

For CRM-side velocity tracking once these leads land in HubSpot, see HubSpot to Google Sheets for RevOps. For broader marketing attribution context, see Why Marketing Attribution Is Broken in 2026.

Comparing the three methods

Aspect Manual CSV Apps Script Scheduled connector
Setup time 5 min 2–4 hr + app review wait Under 10 min
Cost Free Free From $35/mo
Firmographic breakdowns One dimension at a time Single-pivot per call Cross-pivot in one query
Lead Gen form data Separate export Separate endpoint + manual merge Integrated in same query
Scheduled refresh No Yes (Apps Script triggers) Yes (built-in, hourly/daily)
Multi-account One export per account Loop in code Native, single query
Token rotation N/A Manual every 60 days Handled by connector
Code maintenance None Owner Vendor

The decision normally comes down to number of ad accounts and team appetite for code. One account, you have an engineer: Apps Script. Multiple accounts or B2B is your full-time job: scheduled connector. Quarterly board deck only: manual CSV.

LinkedIn-specific quirks worth knowing

Five LinkedIn behaviors that affect every method and every dashboard you build:

  • 60-day token rotation. No method is exempt. Plan a re-auth ritual or build refresh-token logic. Skip this and your daily refresh fails on day 61.
  • LinkedIn-Version header changes quarterly. API versions follow YYYYMM format. Forgetting to bump it after 6 months gives a 400 with a "version deprecated" error.
  • r_ads_leadgen_automation scope requires app review. This is the most common reason "my Lead Gen data is empty" — the scope wasn't granted, so the API returns silently empty arrays instead of an error.
  • Single-pivot per adAnalytics call. Cross-tabulation across MEMBER_SENIORITY × MEMBER_COMPANY_SIZE × MEMBER_INDUSTRY requires multiple calls and a Sheets-side merge. Plan the API call budget.
  • Attribution window matters. LinkedIn UI default is 30-day post-click + 7-day view-through. API lets you set this per call. If Sheets numbers don't match Campaign Manager, the attribution window is the first suspect.

Common errors and how to read them

A few errors show up often enough that recognizing them saves debugging time.

401 Unauthorized: access token expired (the 60-day clock) or scopes changed. Re-run the OAuth flow. In Dataslayer, click the LinkedIn connection in the connection panel and re-authenticate.

429 Too Many Requests: you hit a LinkedIn rate limit. Standard app tiers cap analytics calls at a few hundred per day; Marketing Developer Platform partners get higher. Fix: stagger pulls, batch campaigns into one call, or move to a partner tier.

Empty elements array with no error: the most common Lead Gen problem — r_ads_leadgen_automation scope not granted. Verify in the LinkedIn Developer Portal that the app has the scope approved, then re-authenticate.

400 Bad Request — "Invalid pivot value": you used pivot=MEMBER_TITLE but the current API version uses MEMBER_JOB_TITLE. The pivot vocabulary occasionally renames; check the Marketing API reference for the version you're calling.

Conversions count mismatch with UI: the UI uses the campaign's saved attribution window; the API uses whatever window you specified in the call. If your Sheet shows different conversions than Campaign Manager, the attribution window is the cause 80% of the time.

FAQ

Why does LinkedIn cost so much more per click than Google or Meta?
B2B targeting is expensive because the audience is small and the buyer is valuable. The right comparison isn't CPC, it's cost per closed-won deal — which is what the firmographic waterfall in Dashboard 2 actually computes. A $25 CPC that produces $50K customers is cheaper than a $2 CPC that produces $200 customers.

Do I need Marketing Developer Platform partnership to use the LinkedIn Marketing API?
Yes for production use of r_ads_reporting and r_ads_leadgen_automation at scale. LinkedIn auto-approves Marketing Developer Platform for most legitimate marketing/agency use cases, but the review takes 3–10 business days. For internal experimentation, you can use the API with a basic developer app under lower rate limits before approval.

Why are my Lead Gen form responses showing as empty?
The single most common cause: the r_ads_leadgen_automation scope isn't granted. Even if your app was approved, you may need to re-authenticate after LinkedIn adds the scope. Check Settings → API Keys in your developer app and re-run OAuth.

Can I match LinkedIn impressions to my ABM target account list?
Yes — pull adAnalytics with pivot=COMPANY to get impression/click/spend metrics per named account, then VLOOKUP against your ABM list in Sheets. Dashboard 1 above is built on this pattern.

Is LinkedIn Conversions API the same as externalWebsiteConversions?
No. externalWebsiteConversions is the read-side metric (a count of Insight Tag conversions). The Conversions API (CAPI) is the write-side endpoint where you push offline conversions back to LinkedIn for attribution. This post covers the read direction.

How often should I refresh LinkedIn data for ABM tracking?
Daily at minimum. ABM accounts buy on quarter-end cycles; weekly refresh means you miss the buying-committee activation that happens over 3–5 days. The hourly tier on Dataslayer's Advanced plan or an Apps Script trigger at 6 AM daily is the typical setup.

Does the LinkedIn API give me LinkedIn Live event data or organic post engagement alongside ads?
Organic content requires the r_organization_social scope and a different API endpoint (/rest/organizationalEntityShareStatistics). It's a separate workflow from ads reporting; combining the two means two API calls and a Sheets-side merge by company page ID + date.

Conclusion

Three methods for getting LinkedIn Ads data into Google Sheets exist on a spectrum: manual CSV for quarterly audits, Apps Script for engineering-heavy teams who can absorb the 60-day token rotation and the app review wait, scheduled connector for B2B teams running multi-account or multi-pivot reporting without engineering bandwidth.

But the methods are means, not the end. The deliverable is the two B2B reports: an ABM account-level engagement tracker that shows which named accounts are warming up, and a firmographic lead-gen waterfall that quantifies which job seniority × company size × industry combinations actually convert to revenue. Both require pulling the firmographic pivots and joining to CRM data — and most teams skip those pivots on their first Lead Gen export, then wonder why their LinkedIn-to-Sheets workflow doesn't change how the marketing budget gets allocated.

Pull the firmographic dimensions. Build the dashboards. The connector is a Tuesday afternoon of setup; the firmographic insight is something you'll act on every quarter for the next year. Start a free Dataslayer trial if you want to skip the API maintenance and get to the dashboards faster.

HOW CAN WE HELP?

Knowledge baseSupport ticketContact

RELATED POST

How to Connect Klaviyo to Google Sheets for Ecommerce Email and SMS Attribution

Meta's AI Business Assistant Goes Global: What Marketing Reporting Teams Need to Track Now

Visual Query Builder vs SQL: Which One Should Your Marketing Team Use?

Our Partners

Google Cloud Partner
Microsoft Partner