Integrations
Three ad APIs, one model
Define a campaign once, and let an adapter translate it for each network. The hard part is knowing what to unify and what to leave different, because some of what looks the same isn't.
By itmarkerz Technologies. Updated 30 October 2026.
The project
For a Belgian marketing company, a six-person team of ours spent about a year building a multi-channel advertising platform on Laravel and React. Account managers define a campaign once and publish it to Facebook, Instagram and Google through the Meta Marketing API, Instagram Graph API and Google Ads API. Scheduling has approval steps. Pausing, resuming and changing budgets happen across networks in one action. Metrics sync daily.
Your model isn’t theirs
The temptation is to copy one network’s structure and force the other into it. Meta organises around campaigns, ad sets and ads, while Google organises around campaigns, ad groups and ads, and these levels don’t hold the same settings. Instead, describe what the account manager wants, and let each adapter work out how to express it.
| Concern | Shared model | Adapter |
|---|---|---|
| Objective | What the customer wants to achieve | Map to the network’s own objective or campaign type |
| Audience | A description, with targeting choices | Translate to each network’s targeting options; say so if one can’t do it |
| Budget and dates | Amount, currency and period | Where the budget sits, and its minimum and rules |
| Creative | Copy and media | Formats and size checks per network, before submitting |
| Status | Draft, approved, scheduled, live, paused | Translate each network’s review and delivery states |
| Identifiers | Your ID | The network’s IDs, stored per campaign and per level |
Keep the adapter interface small
interface AdNetwork
{
public function validate(CampaignDraft $draft): ValidationResult;
public function publish(CampaignDraft $draft): PublishedRefs;
public function setStatus(PublishedRefs $refs, Status $status): void;
public function setBudget(PublishedRefs $refs, Money $budget): void;
public function dailyMetrics(PublishedRefs $refs, Date $day): NetworkMetrics;
}This sketch is illustrative, not our client’s code. What matters is validate: each network’s rules should run before the account manager submits, so that they fix problems in your screen and not three API errors later. Save each network’s raw error too, because you will need the original when something unusual comes back.
One network’s outage shouldn’t block the others
On this platform, every network call runs on background queues, so one network being down never holds up the others. That has knock-on effects for the product. A campaign can be live on Google and failed on Facebook, so “published” isn’t one status: show the state per network, and let people retry only the part that failed. Publishing has several steps at each network too. If the third step fails, you need to know what the first two created, which is why the references are saved after every step.
Don’t merge attribution
The platform stores daily metrics in one schema for cross-channel reporting per customer, but shows each network’s attribution side by side and doesn’t merge them. This was a deliberate decision. Networks count conversions under their own rules and each can claim credit for the same sale, so adding them together gives a total that no one can defend. Spend and impressions can sit together more safely. For conversions, label the source and let the customer see the difference.
Reported figures can also change for some days after the fact as networks finalise them. Fetch recent days again rather than treating yesterday’s number as final, and tell users which figures may still move.
Tokens belong to customers
The platform is multi-tenant: every customer has its own connected ad accounts, users and encrypted tokens. A token is authority to spend someone’s money, so encrypt it at rest, scope every job to one customer, and keep it out of your logs. Build the flow for a token that has stopped working from the start, because the person who connected the account will eventually leave. Campaigns should raise a clear message for a named person, not silently stop reporting.
The same adapter thinking applies to other integrations too, as you can see on our integration services page.
The platform described here
One dashboard to build, schedule, publish and report on Facebook, Instagram and Google campaigns for a Belgian marketing company's enterprise customers. Laravel + React, three advertising APIs, multi-tenant with encrypted per-customer tokens. One year, six people.
- Sector
- Marketing & advertising
- Region
- Belgium
- Stack
- Laravel, React, Meta Marketing API, Instagram Graph API, Google Ads API
- Engagement
- Product build, about one year, six people
Questions
Why not use a marketing platform that already does this?
Many teams should. A custom build made sense for our client because the workflow, approvals and customer reporting were the product. If you only want to manage your own ads, the networks' own tools or an existing product will be cheaper.
Do these APIs need approval?
Expect some. Google Ads API access uses a developer token as well as OAuth, and Meta apps need the right permissions and may need review before managing other people's ad accounts. Requirements change, so read the current documentation early, since this can affect your timeline more than the code does.
More on integrations
- Stripe Direct Debit, Xero, QuickBooks and Sage: a UK finance integration mapEach system by method, sync direction, limits and how it fails.
- Stripe Bacs Direct Debit: pending states, failures and reconciliationThe timeline, the events, what each failure means and how to match payouts.
- Connecting to Sage 50: why we ship a daily journal fileWhen a file beats a live connection, and how to make it safe to import.
- Xero integration: what to sync and what to leaveCurrent API limits, a sync table, and the failures to design for.
- A bot on the same API as your websiteWhy a Telegram bot shouldn't have its own business logic.
Building on more than one ad network?
Tell us which networks you need and who will use the tool. We will tell you whether to build it, and how we would structure it.
We reply within one business day (IST).