FacebooK Custom Audience API Creation

Tue Feb 27 2018

Facebook API is quite robust and you have a lot of loose ends you need to cover. You need to handle limits for your app, for your user, for your account and much more.

Our recent project was to sync our local users lists in to Facebook “Custom Audience”.

On the surface it sounds super simple:

  • create a custom audience
  • with the new audience id, send the list of users
  • Done 🙂

Well not quite

What do you do if you have lists of millions of users? You probably cant send all of them at once.

Facebook limits you to sending chunks of 10K per request.

No problem, let’s run a quick loop in chunks of 10K and on each rotation send a request to Facebook.

But not quite there yet

What happens now when you got an api throttle from Facebook and you need to wait for several minutes so they will let you back in.

Another solution, now we have jobs queue that runs those request.

We run over the 10K chunks loop and in the case we get throttled, we make sure to get the index of the last synced user.

Now we create a new job that has that user id, so when it will run it will make sure to start from that user and not resend all the old users again.

The above solution worked great and now we are researching for implementing “refresh” or “sync” of our list with custom audience. Facebook doesn’t really like that by their docs, and they don’t offer you that feature.

We should think of a workaround for that but till now I couldn’t find any other provider that offer that feature so it will surely be a great challenge.

pseudocode example: {#pseudocodeexample}
# Job
run(data):  
    chunkSize = 10K
    startIndex = data['start'] || 0
    curr = startIndex

   listId = data['listId'] || null

    if is_null(listId):
        listId = FB.createList()

    try:
        while True:
            usersChunk = UsersRepo.fetch(curr, chunkSize)
            if empty(usersChunk):
                break
            FB.addToList(usersChunk)
            curr += chunkSize
    catch ex:
        # handle exception however u need
        log('job was splitted')
        return createJob({startIndex: curr, listId: listId})

    log('job was completed')