Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Set Up a Custom Ad Serving Platform in FlutterFlow

Build a self-serve ad platform within your FlutterFlow app. Advertisers create campaigns in Firestore with creative images, target URL, placement type, budget, and targeting criteria. Ad display Components query active campaigns for the appropriate placement, track impressions and clicks in a Firestore subcollection, and use Cloud Functions to enforce budgets and pause campaigns when spend limits are reached. An admin dashboard shows performance metrics including click-through rate.

What you'll learn

  • How to design an ad campaign data model with targeting and budgets
  • How to build ad display Components for banner and interstitial placements
  • How to track impressions and clicks with frequency capping
  • How to enforce campaign budgets with Cloud Functions
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read25-30 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build a self-serve ad platform within your FlutterFlow app. Advertisers create campaigns in Firestore with creative images, target URL, placement type, budget, and targeting criteria. Ad display Components query active campaigns for the appropriate placement, track impressions and clicks in a Firestore subcollection, and use Cloud Functions to enforce budgets and pause campaigns when spend limits are reached. An admin dashboard shows performance metrics including click-through rate.

Building an In-App Ad Serving Platform in FlutterFlow

Instead of using third-party ad networks, you can build your own ad serving system for direct advertiser relationships. This tutorial creates campaign management, ad rendering for banner and interstitial placements, impression and click tracking with frequency capping, and budget enforcement via Cloud Functions.

Prerequisites

  • A FlutterFlow project with Firestore and Cloud Functions configured
  • Firebase Storage for ad creative images
  • Understanding of Firestore queries and Cloud Functions triggers
  • An existing app with pages where ads will be displayed

Step-by-step guide

1

Design the Firestore data model for campaigns and tracking

Create an ad_campaigns collection with fields: advertiserId (String), title (String), imageUrl (String, the ad creative), targetUrl (String, where clicks go), placement (String: banner or interstitial), impressionCount (int, default 0), clickCount (int, default 0), budget (double, total spend limit), costPerClick (double), currentSpend (double, default 0), isActive (Boolean), targeting (Map with optional fields: categories array, regions array). Create an ad_impressions subcollection under each campaign: userId (String), timestamp (Timestamp), type (String: impression or click).

Expected result: Firestore has an ad_campaigns collection with tracking subcollections ready for impression and click data.

2

Build the campaign management page for advertisers

Create a CampaignManagement page. Display a ListView of the advertiser's campaigns showing: title, ad preview image, placement type badge, impressionCount, clickCount, click-through rate (clicks divided by impressions as percentage), currentSpend versus budget progress bar, and an active/paused Switch toggle. Add a Create Campaign form with: title TextField, image upload FlutterFlowUploadButton, target URL TextField, placement DropDown (banner or interstitial), budget TextField (number), costPerClick TextField (number), and targeting category ChoiceChips. On create, save to Firestore with isActive true.

Expected result: Advertisers can create and manage campaigns with performance metrics and active/paused controls.

3

Create the banner ad display Component

Build a BannerAd Component that can be placed on any page. The Component runs a Backend Query on ad_campaigns where placement equals banner, isActive equals true, and optionally matches the page's category if targeting is set. Pick a random campaign from results using a Custom Function that generates a random index. Display the campaign's imageUrl in a Container with a GestureDetector. On display, create an ad_impression document with type 'impression' and increment impressionCount on the campaign. On tap, create an impression with type 'click', increment clickCount, increment currentSpend by costPerClick, and launch the targetUrl.

Expected result: Banner ads appear on pages, serve random active campaigns, and track impressions and clicks.

4

Implement frequency capping to limit user exposure

Without capping, the same user sees the same ad repeatedly, inflating impression counts. Add an App State variable adImpressionCounts (JSON Map, default empty) that tracks campaignId to impression count for the current session. Before displaying an ad, check if adImpressionCounts[campaignId] exceeds 3. If it does, skip that campaign and select the next one from the query results. Increment the counter after each display. For cross-session capping, store daily impression counts in a Firestore document under the user: users/{uid}/ad_caps/{campaignId} with count and date fields.

Expected result: Each user sees a maximum of 3 impressions per campaign per day, preventing metric inflation.

5

Build a Cloud Function to enforce budget limits

Create a Cloud Function that triggers on every new ad_impression document where type equals 'click'. The function reads the campaign's currentSpend and budget fields. If currentSpend plus costPerClick exceeds budget, set isActive to false on the campaign document, pausing it automatically. Send a notification to the advertiser that their campaign has reached its budget limit. This prevents overspend and ensures ads stop serving once the budget is exhausted.

enforce_budget.ts
1// Cloud Function: enforceBudget
2import * as functions from 'firebase-functions';
3import * as admin from 'firebase-admin';
4admin.initializeApp();
5
6export const enforceBudget = functions.firestore
7 .document('ad_campaigns/{campaignId}/ad_impressions/{impressionId}')
8 .onCreate(async (snap, context) => {
9 const data = snap.data();
10 if (data.type !== 'click') return;
11
12 const campaignRef = admin.firestore()
13 .doc(`ad_campaigns/${context.params.campaignId}`);
14 const campaign = (await campaignRef.get()).data();
15 if (!campaign) return;
16
17 const newSpend = (campaign.currentSpend || 0) + campaign.costPerClick;
18 const updates: any = { currentSpend: newSpend };
19
20 if (newSpend >= campaign.budget) {
21 updates.isActive = false;
22 }
23 await campaignRef.update(updates);
24 });

Expected result: Campaigns automatically pause when their budget is exhausted, preventing overspend.

6

Build the admin analytics dashboard for ad performance

Create an AdAnalytics page showing aggregate metrics across all campaigns. Display total impressions, total clicks, overall CTR (click-through rate), and total revenue (sum of currentSpend across campaigns). Add a ListView of all campaigns sorted by CTR descending showing the top performers. For each campaign show: title, impressions, clicks, CTR percentage, spend vs budget bar. Optionally add a time filter (Today, This Week, This Month) that queries ad_impressions by timestamp range and recalculates metrics.

Expected result: An admin dashboard shows ad platform performance with per-campaign metrics and revenue tracking.

Complete working example

FlutterFlow Ad Serving Platform Setup
1FIRESTORE DATA MODEL:
2 ad_campaigns/{campaignId}
3 advertiserId: String
4 title: String
5 imageUrl: String (ad creative)
6 targetUrl: String (click destination)
7 placement: "banner" | "interstitial"
8 impressionCount: int (default 0)
9 clickCount: int (default 0)
10 budget: double (total spend limit)
11 costPerClick: double
12 currentSpend: double (default 0)
13 isActive: Boolean
14 targeting: { categories: [String], regions: [String] }
15 ad_impressions/{impressionId}
16 userId: String
17 timestamp: Timestamp
18 type: "impression" | "click"
19
20APP STATE:
21 adImpressionCounts: JSON Map = {} (campaignId count per session)
22
23WIDGET TREE BannerAd Component:
24 Container (height: 80, full width, card style)
25 Backend Query: ad_campaigns
26 where placement == 'banner'
27 where isActive == true
28 Custom Function: pickRandom + check frequency cap
29 GestureDetector (onTap log click + launch targetUrl)
30 Stack
31 Image (campaign.imageUrl, BoxFit.cover)
32 Positioned (top-right)
33 Container (tiny 'Ad' label, semi-transparent)
34
35WIDGET TREE Campaign Management:
36 Column
37 Text ('My Campaigns', Headline Small)
38 ListView (advertiser's campaigns)
39 Container (card)
40 Row
41 Image (ad preview, 60x60)
42 Column
43 Text (title)
44 Text (impressions + ' views | ' + clicks + ' clicks')
45 LinearPercentIndicator (currentSpend / budget)
46 Switch (isActive toggle)
47 Button 'Create Campaign' form
48
49CLOUD FUNCTION: enforceBudget
50 Trigger: ad_impressions onCreate
51 Logic: if click update currentSpend
52 if currentSpend >= budget set isActive = false

Common mistakes

Why it's a problem: Counting impressions on every page load without frequency capping

How to avoid: Implement frequency capping: track impressions per user per campaign in App State or Firestore and limit to 3 per day.

Why it's a problem: Not enforcing budgets server-side with Cloud Functions

How to avoid: Use a Cloud Function triggered on every click impression to check and enforce the budget atomically on the server.

Why it's a problem: Serving ads without an 'Ad' label on the creative

How to avoid: Add a small semi-transparent 'Ad' label positioned in the corner of every ad creative using a Stack with a Positioned widget.

Best practices

  • Implement frequency capping to limit impressions per user per campaign per day
  • Enforce budgets server-side with Cloud Functions to prevent overspend
  • Label all ad placements with a visible 'Ad' indicator for transparency
  • Track both impressions and clicks separately for accurate CTR calculation
  • Use random campaign selection from active campaigns for fair distribution
  • Auto-pause campaigns when budget is exhausted via Cloud Function
  • Show advertisers clear performance metrics: impressions, clicks, CTR, and spend

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a custom in-app ad serving platform in FlutterFlow. Advertisers create campaigns with images, target URLs, budgets, and targeting. Banner ads display on pages, track impressions and clicks with frequency capping, and Cloud Functions enforce budgets. Show me the data model, ad display Component, and budget enforcement Cloud Function.

FlutterFlow Prompt

Create a campaign management page with a list of ad campaigns showing preview images, click counts, and budget progress bars. Add a create campaign form with image upload and budget fields.

Frequently asked questions

How do I implement interstitial (fullscreen) ads?

Show a fullscreen overlay using a Container with 100% width and height in a Stack at the page level. Display the ad creative with a Close button that appears after 3 seconds using a delayed Timer action. Track the impression on display and click if the user taps the creative.

Can I target ads based on user interests?

Yes. Store user interests on their user document. When querying campaigns, filter by matching the campaign's targeting.categories against the user's interests array.

How do I bill advertisers for their ad spend?

Use Stripe to pre-charge advertisers for their campaign budget. Deduct from the pre-paid balance on each click via Cloud Function. When the balance reaches zero, pause the campaign and prompt for top-up.

How do I prevent click fraud?

Track clicks per user per campaign. If a single user clicks the same ad more than 3 times per day, stop counting additional clicks toward spend. Log suspicious patterns for manual review.

Can I support video ads?

Yes. Add a videoUrl field to campaigns. Use FlutterFlowVideoPlayer for video ad creatives. Track a 'view' impression only after 3 seconds of playback, and a 'completed' event at the end.

Can RapidDev build an ad platform for my app?

Yes. RapidDev can build complete ad serving systems with campaign management, programmatic targeting, real-time bidding, fraud detection, and advertiser billing.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.