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.

What belongs in a shared campaign model and what belongs in each adapter
ConcernShared modelAdapter
ObjectiveWhat the customer wants to achieveMap to the network’s own objective or campaign type
AudienceA description, with targeting choicesTranslate to each network’s targeting options; say so if one can’t do it
Budget and datesAmount, currency and periodWhere the budget sits, and its minimum and rules
CreativeCopy and mediaFormats and size checks per network, before submitting
StatusDraft, approved, scheduled, live, pausedTranslate each network’s review and delivery states
IdentifiersYour IDThe 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

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).