Connect Facebook (Meta) Ads to Power BI: Example

17 Oct 2026 · 9 min read

Connect Facebook (Meta) Ads to Power BI through a suitable third-party connector or an Insights API extraction into a supported data source. Start with campaign-by-day spend and clearly labelled attribution. The downloadable example below shows the model, DAX measures and expected totals.

Put Facebook and Instagram ad spend beside the business figures you use to make decisions. Power BI can report campaign costs, link clicks and Meta-attributed purchases alongside separately defined website and store measures.

This guide covers the connection, a bounded Insights API request, a downloadable campaign model and refresh checks. References were checked on 17 October 2026 using Meta's official SDK and other primary sources. The example contains synthetic teaching data, with independently checked arithmetic. It is not a client result or a live Meta extraction. The request and DAX have not been executed against a private ad account or in Power BI Desktop or Service.

Choose how to connect Facebook Ads to Power BI

RouteUseful whenCheck before choosing
Third-party connectorYou want managed extraction into Power BI or a supported destinationAvailable fields, attribution options, history, subscriptions and published refresh
Meta Insights API into staged tablesYou need control of accounts, reporting grain and stored historyAccount access, tokens, API versions, pagination, limits and maintenance
File-based teaching modelYou want to check measures before arranging live accessSource definitions, types and control totals; the download here is illustrative

An API or connector supplies the data. A warehouse or other staged source stores it. They can be parts of the same connection. Our data integration approach covers that reporting architecture.

Microsoft's Power Query connector directory did not list a dedicated Facebook/Meta Ads connector at this review. Evaluate the specific partner route and its Power BI host support.

Define the account, dates and attribution first

For a first report, use one ad account, campaign level, daily rows and one documented reporting basis. Keep the ad account ID in every key; campaign names are display labels that can change.

Record the account timezone and currency, selected reporting dates, click definition, purchase action type, attribution window and extraction timestamp. Decide whether action reporting follows the ad-interaction date or conversion date before comparing daily figures.

The request below chooses action_report_time=impression and action_attribution_windows=["7d_click"]. These are explicit example choices, not a claim about an account's Ads Manager defaults. Match the actual supported configuration and comparison report during a live build. Meta's official Insights SDK lists the reporting-time and attribution-window options.

Request daily campaign Insights data

Use a Meta app and server-side token authorised to read the selected ad account. Check ads_read, the account assignment and the access requirements for your app's use case. Grant access only to the agreed assets. Meta's official Marketing API Postman collection provides request examples; its Business SDK documents setup and API use.

Set these server environment variables before adapting the template:

  • META_GRAPH_VERSION: an API version supported by your app, including its v prefix. Pin it and review upgrades.
  • META_AD_ACCOUNT_ID: the numeric account ID without the act_ prefix.
  • META_ACCESS_TOKEN: the authorised token, kept outside shared PBIX files, browser code and downloads.

This read-only request asks for two reporting dates at campaign level. Its parameters and fields were checked against Meta's ad-account SDK implementation. Account permissions and returned metric availability still need verification with your own account.

curl --get \
  "https://graph.facebook.com/${META_GRAPH_VERSION}/act_${META_AD_ACCOUNT_ID}/insights" \
  --header "Authorization: Bearer ${META_ACCESS_TOKEN}" \
  --data-urlencode 'level=campaign' \
  --data-urlencode 'time_increment=1' \
  --data-urlencode 'time_range={"since":"2026-09-14","until":"2026-09-15"}' \
  --data-urlencode 'fields=account_id,account_currency,campaign_id,campaign_name,date_start,date_stop,spend,impressions,inline_link_clicks,actions,action_values' \
  --data-urlencode 'action_report_time=impression' \
  --data-urlencode 'action_attribution_windows=["7d_click"]' \
  --data-urlencode 'limit=100'

The page limit does not establish complete coverage. Follow the returned pagination, check errors and reconcile the selected campaigns and dates. Meta's SDK cursor implementation shows pagination handling. Keep tokens and credential-bearing pagination URLs out of logs. Respect rate-limit responses and monitor token expiry or revoked access; a failed request is different from a checked empty result.

For large extracts, check the asynchronous Insights reporting route and current limits for your pinned API version. Validate the small report first instead of assuming that one synchronous response covers an account's history.

Flatten purchase metrics without multiplying spend

The response includes scalar cost fields and action arrays. Select one verified website-purchase action_type from the account's returned actions array and the entry with the same action_type in action_values. Keep its identity in the staged data.

Extract those selected values into scalar columns on the campaign-day row, or store actions in a separately keyed fact table. Expanding and joining both arrays directly can multiply rows and repeat spend. Adding several purchase-like aliases can count the same underlying outcome again.

The teaching CSV uses TEACHING_WEBSITE_PURCHASE as its action label. This is an invented modelling label, not an API action identifier to request. A live build must use the verified account-returned key. An omitted or unavailable action value needs checking before it can be treated as zero. Preserve source numeric precision; the sample's whole counts do not establish that every live reported count is an integer.

Work through the Power BI example

Download the worked example ZIP, or inspect the daily campaign CSV, DAX measures, expected results and README. Access is ungated.

The CSV is a normalised synthetic extract, not a Meta API response. It contains two fictional campaigns over 14–15 September 2026, one account, Europe/London reporting time and assumed GBP values. It uses impression-date action reporting and the chosen seven-day-click basis. Its IDs, purchase-action label and extraction timestamp are illustrative.

DateCampaignSpendImpressionsLink clicksReported purchasesReported purchase value
14 SeptemberA£10010,00020010£600
14 SeptemberB£30015,00015015£900
15 SeptemberA£15012,00018012£720
15 SeptemberB£508,0001603£180
CombinedBoth£60045,00069040£2,400

Import the sample and add the measures

  1. In Power BI Desktop, choose Get data → Text/CSV, select campaign-daily.csv and open Transform Data.
  2. Name the query MetaCampaigns. Set date_start and date_stop to Date; spend and reported_purchase_value to Fixed Decimal Number; and the three sample count fields to Whole Number. Keep IDs and reporting-basis metadata as Text. Live metric types must preserve the actual source values.
  3. Choose Close & Apply. Add each definition below as a separate measure. Create cards for the totals and a table by date_start and campaign_id.
Ad Spend = SUM ( MetaCampaigns[spend] )

Impressions = SUM ( MetaCampaigns[impressions] )

Link Clicks = SUM ( MetaCampaigns[inline_link_clicks] )

Meta Reported Purchases = SUM ( MetaCampaigns[reported_purchases] )

Meta Reported Purchase Value = SUM ( MetaCampaigns[reported_purchase_value] )

Link CTR = DIVIDE ( [Link Clicks], [Impressions] )

Cost per Link Click = DIVIDE ( [Ad Spend], [Link Clicks] )

Cost per Reported Purchase = DIVIDE ( [Ad Spend], [Meta Reported Purchases] )

Meta Reported ROAS = DIVIDE ( [Meta Reported Purchase Value], [Ad Spend] )

Cost per Thousand Impressions = DIVIDE ( [Ad Spend] * 1000, [Impressions] )

Format Link CTR as a percentage with two decimals, Meta Reported ROAS as a decimal ratio, and the monetary measures as GBP with two decimals. These ratios use the stated source fields; Link CTR is distinct from an all-click CTR or an outbound-click measure.

Reconcile the control totals and weighted ratios

The combined report should show £600 spend, 45,000 impressions, 690 link clicks, 40 reported purchases and £2,400 reported purchase value. Expected ratios are:

  • Meta-reported ROAS: £2,400 ÷ £600 = 4.00.
  • Link CTR: 690 ÷ 45,000 = 1.53% after rounding.
  • Cost per link click: £600 ÷ 690 = £0.87 after rounding.
  • Cost per reported purchase: £600 ÷ 40 = £15.00.
  • Cost per thousand impressions: £600 ÷ 45,000 × 1,000 = £13.33 after rounding.

Calculate ratios from summed numerators and denominators. The four row ROAS values are 6.0, 3.0, 4.8 and 3.6. Averaging them gives 4.35, which weights the spend incorrectly; the combined result is 4.00.

Store one current row per account, campaign, reporting day and reporting basis. Replace repeat extractions at that grain and keep audit snapshots separately. Combining campaign totals with ad-level rows, or summing overlapping extracts, repeats the same activity.

Compare Meta, GA4 and store figures on their own definitions

Keep three measures visible when the report needs them:

MeasureWhat its label needs to explain
Meta-reported purchase valueSelected action type, attribution window, action reporting time and extraction date
GA4-attributed purchase revenueRevenue definition, attribution model, relevant dimension scope, dates and consent coverage
Store sales or net revenueOrder/refund date basis, discounts, tax, shipping, cancellations and currency

Joining these sources does not make one the definitive attribution answer. Their claims can overlap. Keep platform-reported values separate when comparing channels; adding Meta and Google Ads attributed revenue can count sales claimed by both platforms. The example's ROAS is a reported advertising ratio, not profit, causal lift or a client outcome.

Google explains GA4 attribution and the scope of attribution settings. GA4 also supports campaign cost-data import, including supported third-party sources. Choose Power BI when the separate business model and controls are useful.

Use the GA4 connection guide for website data, the Google Ads guide for that cost source and the Shopify guide for order and refund reconciliation. Shared date, campaign and account dimensions should preserve each source's grain; avoid uncontrolled fact-to-fact joins. Convert currency using a documented rate and date before combining accounts in different currencies.

Publish and check scheduled refresh

For a live connection, run the authorised Meta extraction into a supported staged source, then refresh the Power BI semantic model. Keep the token in the extraction environment; Power BI reads the staged source using its own credentials.

Check the published connection, privacy settings and any required gateway. Run a refresh in the Service and compare its history, row counts, source timestamp and sample campaign totals with the extract. A successful Desktop import alone does not establish scheduled refresh. Microsoft's Power BI refresh guidance and our gateway guide cover that side of the build.

For a reporting project, tell us about your Meta Ads setup: which ad accounts and stores you use, which figures you want to compare and how often the report should update. The link opens an editable integration brief. Our ecommerce reporting guide covers the wider store and margin model.

Frequently asked questions

Does Power BI have a native Facebook Ads connector?

Microsoft's Power Query connector directory does not list a dedicated Facebook or Meta Ads connector as checked on 17 October 2026. Third-party connector routes are available. Check the vendor's supported reports, authentication, history and Power BI Service refresh before choosing one.

Why does Meta ROAS differ from GA4 or store revenue?

The systems can use different attribution models, windows, reporting dates, consent coverage and value definitions. Keep Meta-reported purchase value, GA4-attributed revenue and store sales separately labelled. Joining the data does not make the figures equivalent or establish incremental revenue.

Which Meta clicks should I use for CTR and CPC?

Use one documented click measure consistently. This example uses inline_link_clicks, with link CTR equal to those clicks divided by impressions and cost per link click equal to spend divided by those clicks. All-click and outbound-click measures have different meanings.

Can Meta Ads data refresh automatically in Power BI?

Yes, with an authorised extraction and a supported connection. Extract into the staged source before refreshing Power BI, configure published credentials and any required gateway, then check the Service refresh history and source timestamp. A successful Desktop import alone does not verify the schedule.

Do I need Power BI just to compare Meta costs in GA4?

GA4 supports campaign cost-data import, including supported third-party sources. Power BI is useful when you need a separate model spanning ad accounts, store orders, refunds, margins or other business data, with reporting definitions and reconciliation controls you own.

Bring Meta (Facebook) Ads into Power BI

Compare Meta (Facebook) Ads spend with your store results. Share the ad accounts, stores and report you want to include, plus the refresh schedule you need.