Skip to content
HA_

← All writing

· 3 min read

Never act silently in a customer's account

Why ClickFortify never creates anything in a customer's ad account in the background, and what a review step has to show before it does.

productarchitectureadtech

ClickFortify works inside other people's systems. To exclude bad traffic, it has to connect to a customer's Google Ads or Meta account and change things there. That access is central to the product, and it is also the part I am most careful with. One rule came out of that care, and it now shapes every similar case: we never act silently in a customer's account.

Where the rule came from

During the Meta connect work, the suggestion was to create a Meta Pixel automatically when the customer didn't have one. On the surface it sounded helpful. The customer needs a pixel, we can make one, so why ask?

I rejected it. Not because a pixel is dangerous, but because of what the shortcut assumes: that we know better than the customer what should exist in their account, what it should be called, and where it should live. We don't. It is their account.

What we do instead

Any flow that would provision something in a customer's external account shows a review step first. That step has four parts:

  • An editable name. We suggest one, and the customer can change it.
  • Where it will be created. The account or business it will sit under, stated plainly.
  • What we will do with it. One honest sentence about why we need it.
  • A Create button the customer presses. Nothing happens in the background.

Defaults are fine. A good default saves the customer time, and most people will accept it. Silent execution is not fine. The difference is small in effort and large in meaning: with a default, the customer decides; without the review step, we decide for them.

The rule is not specific to pixels. It covers anything we might provision in a customer's account, whether that is a tag, an audience or some other entity on the platform.

// Illustrative: a change we propose, but never apply on our own
type ProposedAction = {
  kind: 'create';
  resourceType: string;  // what will be created
  name: string;          // suggested by us, editable by the customer
  parentId: string;      // the account or business it will live under
  purpose: string;       // what we will do with it, in plain words
  confirmedBy?: string;  // empty until the customer presses Create
};

The useful property is the last field. Until a person has confirmed the action, it is only a proposal.

Why it matters

The customer keeps control of naming and placement. An ad account is rarely used by one person or one tool alone. A resource with a name nobody chose, sitting under a business nobody picked, is clutter at best and confusion at worst.

Trust is the product. A customer who connects their ad account is lending us their keys. If they discover something we created without asking, the next question is what else we did. Silent creation feels paternalistic, even when the intent is good.

Surprises in someone else's system are expensive. We don't own the customer's account, and we can't see everything else that happens in it. A change that looks harmless from our side can collide with someone's naming scheme or reporting.

It makes support and reversal easier. When the customer created something on purpose, through a screen that told them what it was for, they know where it came from. If they want to undo it, they know what to look for. A background action leaves them to work it out.

Beyond creating things

The same reasoning applies to anything a product does in an external system, not only creating resources. An exclusion written into an ad account is a change to someone else's setup too. My view is that changes like that should be visible and attributable: the customer should be able to see what was done, and that it came from us. That is a principle I hold, not a description of every screen we have.

Takeaways

  1. Treat a customer's external account as theirs, even when you have write access to it.
  2. Offer defaults, but put every creation behind a review step with an editable name, its location, its purpose and an explicit confirm button.
  3. Model provisioning as a proposal that becomes an action only after a person confirms it.
  4. Ask whether the customer would be surprised to find the change later. If so, don't make it silently.