facebook / facebook-ruby-business-sdk

Ruby SDK for Meta Marketing API
https://developers.facebook.com/docs/business-sdk
Other
204 stars 161 forks source link

Using multiple Facebook pixels in runtime #154

Open ristovskiv opened 2 years ago

ristovskiv commented 2 years ago

Which SDK version are you using?

v0.11.0.0

What's the issue?

Documentation not clear on how to use multiple Facebook Pixels in runtime

Observed Results:

This is the example on the Facebook page about using the API. From what I can understand is that every Facebook Pixel ID is paired with an Access Token. This is the short excerpt of how to set the facebook pixel id, but this is done globally though

require 'facebook_ads'

access_token = '<ACCESS_TOKEN>'
pixel_id = '<ADS_PIXEL_ID>'

FacebookAds.configure do |config|
  config.access_token = access_token
end

Now I've dived into the code a bit and from a first short overview it looks to me that currently it's impossible to use multiple Facebook Pixel Apis, because it's impossible to set multiple Access Tokens or change them in runtime.

I also want to be kept in mind that I'm not excluding the fact that might be wrong of course. If that's the case can someone maybe point me to the right direction on how to send for instance two Server Side Event Requests with different Facebook Pixel Ids?

If this turns out to be correct, I'm of course willing to work on this issue and provide PR, unless it's in your roadmap already.

stale[bot] commented 2 years ago

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. Thank you for your contributions.

sblackstone commented 2 years ago

This still appears to be an issue, I'm attempting to use FacebookAds::ServerSide::EventRequest - rails active job shares class definitions between instances.

sblackstone commented 2 years ago

Here's a workaround...

The event request can accept an http_executor, you can construct one that matches the internals of the gem to make it seamless. The only thing I didn't support here was app secret - but you should be able to add it easily if you need it.

This is thread-safe.....

class RequestExecutor

  def initialize(session)
    @session = session
  end

  def execute(url, request_method, headers, params)
    newParams = {
      data: params[:data].to_json
    }

    newParams[:test_event_code] = params[:test_event_code] if params[:test_event_code]

    # This part is adapted from FacebookAds::ApiRequest
    faraday_response = @session.request(request_method.downcase.to_sym, url, newParams)

    api_response = FacebookAds::APIResponse.new(faraday_response.status, faraday_response.headers, faraday_response.body)

    if faraday_response.status.to_i >= 500
      raise FacebookAds::ServerError.new(api_response)
    elsif faraday_response.status.to_i >= 400
      raise FacebookAds::ClientError.new(api_response)
    end

    json_response_object = JSON.parse(api_response.body)

    return FacebookAds::ServerSide::EventResponse.new(
        events_received: json_response_object["events_received"],
        messages: json_response_object["messages"],
        fbtrace_id: json_response_object["fbtrace_id"]
    )
  end
end

### Define all your event stuff here, CustomData, UserData, etc...

session = FacebookAds::Session.new(access_token: <key>) 

request = FacebookAds::ServerSide::EventRequest.new(
        pixel_id: pixelId,
        events: [fbevent],
        test_event_code: <event code>,
        http_service_client: RequestExecutor.new(session)
)

response =  request.execute
ckybonist commented 2 years ago

Perhaps we could set the session by AdsPixel?

ads_pixel = FacebookAds::AdsPixel.get(fb_pixel_id)
ads_pixel.session.access_token = access_token

request = FacebookAds::ServerSide::EventRequest.new(
  pixel_id: fb_pixel_id,
  events: [fb_event],
  test_event_code: <event code>,
)

request.execute
dan003400 commented 1 year ago

We are also trying to fire events to the conversion api with multiple pixels (we store pixel_id and access_token in our DB) - we then fire postbacks for multiple pixels but it seems the first pixel to call the FacebookAds.configure block will be the only access_token used until the server is restarted.

Is there a way to dynamically set the access_token?

sblackstone commented 1 year ago

@dan003400 Check out the work around I posted above, should be thread safe...

dan003400 commented 1 year ago

@sblackstone - yup seems to be working, would love if this was not needed as a work around. Thank you!

odedharth commented 5 days ago

Any progress on this issue?