Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tag parsing wrong contents array? #37

Open
billboyles opened this issue Jun 23, 2022 · 11 comments
Open

Tag parsing wrong contents array? #37

billboyles opened this issue Jun 23, 2022 · 11 comments

Comments

@billboyles
Copy link

billboyles commented Jun 23, 2022

We are using a server-side tag setup for GTM where the data is passed to the server as a GA4 Purchase event and then sent along to FB CAPI using this Facebook Incubator tag template.

I've written a custom Javascript variable in GTM to parse a Google Analytics ecommerce "products" array and return it in the format FB CAPI wants for "contents":

image

image

As you can see, it takes the price, quantity, and sku for each item and saves them in the correct format. I am explicitly passing this array as "contents":

image

However, trying to pass the purchase events to the server is failing with code 400 and receives the following response:

"error":{"message":"Invalid parameter","type":"OAuthException","code":100,"error_subcode":2804008,"is_transient":false,"error_user_title":"Invalid Contents Parameter","error_user_msg":"The contents parameter you entered doesn\u2019t contain a list of JSON objects. Enter a list of JSON objects that contain the product IDs associated with the event plus information about the products. For example: [{ 'id' : 'ABC123', 'quantity' : '2', 'item_price' : 5.99}, { 'id' : 'XYZ789' , 'quantity' : 2, 'item_price' : 9.99}]","fbtrace_id":"ASsXl7dWNIzLxh8RdCpOp45"}}

Digging in, it seems like the tag is somehow creating its own "content" array and ignoring the one I'm sending. In the process, it seems to be grabbing the wrong field, using "name" instead of "sku". This is the request body it is sending (some data anonymized):

{"data":[{"event_name":"Purchase","event_time":1656000012,"event_source_url":"https://www.customer.com/order/checkout","action_source":"website","user_data":{"client_ip_address":"111.111.111.111","client_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36","ph":"a1b2c3d4e5f6...abcdef","fbp":"fb.1.1111...1111"},"custom_data":{"currency":"USD","value":7.94,"order_id":"4f719af2-3637-42ee-8e8a-28e8f3783858","contents":[{"title":"Homestyle Huddle Wrap","item_price":7.49,"quantity":1}]}}],"partner_agent":"gtmss-1.0.0-0.0.5"}

Specifically, note the contents array:

"contents" : [
   {
      "title" : "Homestyle Huddle Wrap",
      "item_price" : 7.49,
      "quantity" : 1
   }
]

This is not what's being passed, and it actually doesn't match any of our objects- we don't use "title" anywhere in our objects, so this object in this format has to be coming from this tag template.

However, that seems to be making it fail, since FB is expecting "id" but getting "title"? In other words, FB's tag seems to be ignoring the provided "contents" array and instead building its own, but FB CAPI seems to be rejecting the "contents" array built by FB's own tag.

Any thoughts on why this is happening and how to fix it? Why isn't the tag using the "contents" array I have already built and am sending to it, and why is the one it appears to be building failing?

@koconnor3
Copy link

koconnor3 commented Jun 23, 2022 via email

@billboyles
Copy link
Author

I can definitely change that. However, it was working fine for months earlier this year and last year with this exact setup, That also still does not really explain where "title" is coming from.

@billboyles
Copy link
Author

billboyles commented Jun 24, 2022

This does not appear to have resolved the issue.

This is the GA4 client side tag sent to server:

image

Note contents array:

{
   "name": "x-fb-cd-contents",
   "value": [
      {
         "id": 41263689,   
         "item_price": 5,
         "quantity: 1
      }
   ]
}

Server side FB CAPI tag is sending this:

{"data":[{"event_name":"Purchase","event_time":1656101185,"event_source_url":"https://www.customer.com/order/checkout","action_source":"website","user_data":{"client_ip_address":"111.111.111.111","client_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36","ph":"a1b2c3...d4e5f6","fbp":"fb.1.111111.1111111"},"custom_data":{"currency":"USD","value":5.3,"order_id":"c06952e4-1a61-4d4b-8d75-a8f4763af651","contents":"[object Object]"}}],"partner_agent":"gtmss-1.0.0-0.0.5"}

Note the contents array:

"contents": "[object Object]"

It definitely is an array unless it is being transformed by the FB CAPI tag somehow. It's showing as an object, unless "[Object object]" is a string, and I'm unsure how that would be happening. However, I'm now getting this response from FB CAPI:

{"error":{"message":"Invalid parameter","type":"OAuthException","code":100,"error_subcode":2804019,"is_transient":false,"error_user_title":"Server Side Api Parameter Error","error_user_msg":"The parameter $['data'][0]['custom_data']['contents'] must be an array.","fbtrace_id":"AsrqiGyKVnywuvIsxfBeiqd"}}

The "title" stuff is gone but this just created a new issue. This was all working as recently as a month or two ago, even without renaming the "contents" array to "x-fb-cd-contents" or "price" parameter to "item_price". I'm unclear what's changed.

I could try sending the parameters in the client side GA4 tag as something like:

x-fb-cd-contents.id: 41263689
x-fb-cd-contents.item_price: 5
x-fb-cd-contents.quantity: 1

For other customers using user data for deduplication, I'm basically doing that with user_data- sending each of user_data.first_name, user_data.last_name, user_data.phone, and user_data.email as individual parameters in the client side GA4 tag. But I'm not sure how an array of multiple items could be sent that way, especially when I have no way to predict how many items a customer might be ordering.

@billboyles
Copy link
Author

billboyles commented Jun 24, 2022

Removing the contents array entirely just gets me back to the original issue. It's not required, so I was hoping I could at least get purchase tracking back by sending only "value", "currency", and "order_id". I do this for other customers whose setup does not make detailed purchase information available and it works fine.

Here's an example from another customer that is currently working:

image

So I took off "x-fb-cd-contents" and tried this instead:

image

I can't remove the "items" array if I want that data in GA4. But it seems like the FB CAPI tag is grabbing that and trying to convert it to a "contents" array, but we're back to the "title" parameter being put in and not having an "id" parameter.

This gets sent to server:

image

As you can see, no contents array at all.

But the CAPI tag sends this:

{"data":[{"event_name":"Purchase","event_time":1656103066,"event_source_url":"https://www.customer.com/order/checkout","action_source":"website","user_data":{"client_ip_address":"111.111.111.111","client_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36","ph":"a1b2c3...d4e5f6","fbp":"fb.1.111111.11111111"},"custom_data":{"currency":"USD","value":5.3,"order_id":"93a65b23-9f6c-4fbf-a6b0-6b67c521c3af","contents":[{"title":"Sausage Biscuit Combo","item_price":5,"quantity":1}]}}],"partner_agent":"gtmss-1.0.0-0.0.5"}

Here we are with a "contents" array again, and again it weirdly contains a parameter called "title" that is definitely not coming from any of the data sent from the browser side tags, since as you can see none of those tags contain a "title" parameter for any item, even in "items" array intended for GA4's use.

And we're back to the server replying with:

{"error":{"message":"Invalid parameter","type":"OAuthException","code":100,"error_subcode":2804008,"is_transient":false,"error_user_title":"Invalid Contents Parameter","error_user_msg":"The contents parameter you entered doesn\u2019t contain a list of JSON objects. Enter a list of JSON objects that contain the product IDs associated with the event plus information about the products. For example: [{ 'id' : 'ABC123', 'quantity' : '2', 'item_price' : 5.99}, { 'id' : 'XYZ789' , 'quantity' : 2, 'item_price' : 9.99}]","fbtrace_id":"AVcvazXBTEbLQvodKfR49vk"}}

Why is the FB CAPI tag doing this, and how can I avoid it? I don't see how I can include items for GA4 without FB CAPI doing this. Removing the "items" array from the GA4 request entirely isn't a viable option.

@billboyles
Copy link
Author

billboyles commented Jun 24, 2022

Ultimately, the issue seems to be that the FB CAPI tag is taking this:

"items": [
   {
      "name": "Sausage Biscuit Combo",
      "price": 5,
      "quantity": 1,
      "sku": 41263689
   }
]

and turning it into:

"contents": [
   {
      "title": "Sausage Biscuit Combo",
      "item_price": 5,
      "quantity":1
   }
]

But it should be turning it into this:

"contents": [
   {
      "id": 41263689,
      "item_price": 5,
      "quantity": 1
   }
]

or at least this (which would be fine):

"contents": [
   {
      "id": "Sausage Biscuit Combo",
      "item_price": 5,
      "quantity": 1
   }
]

@billboyles
Copy link
Author

These issues seem related:

#20

#27

@Kevpedia
Copy link

the issue is that your items array doesn't have the item_id field, which GA4 requires BTW. That's what is supposed to get mapped to 'id' in the contents array by this commit back in March 2021: 767618f

function getContentFromItems(items) {
    return items.map(item => {
        return {
            "id": item.item_id, // <--- this part right here
            "title": item.item_name,
            "item_price": item.price,
            "brand": item.item_brand,
            "quantity": item.quantity,
            "category": item.item_category,
        };
    });
}

@billboyles
Copy link
Author

billboyles commented Jun 24, 2022

In this case, "sku" is a carryover from older UA ecommerce, where it was a required field. From the Google side, GA4 definitely doesn't require "item_id". After all, it's working fine without it. So it's actually a bit more complicated than saying "item_id" is required.

Regardless, the FB CAPI tag could (and I would argue, should) be handling the issue a lot more gracefully.

For instance, the CAPI could accept a request without "id"- while the error response lists "id", "item_price", and "quantity" as required fields (and I seem to remember them as listed required fields in the dev documentation back before they did everything with the change to "Meta"), I can't find anything in the current documentation saying any of parameters are required. I see this:

image

Note that "title" isn't even a listed as an available field (incidentally, neither are "brand" or "category").

However, even if "id" is required (as seems to be the case), "title" is not (as noted above, it doesn't even to seem to be a documented parameter). So it makes sense to prioritize "id". It could look for "id" first, then if not found, it could look for "sku" or "name" and use that as "id" instead, only including "name" if it already has "id".

Barring either of the above, It could simply not send the "contents" array if it can't match required fields, instead of failing out the entire request, since only "currency" and "value" are required. It seems like this is the kind of basic check that good code would make. I'm sure Facebook would rather accept the request in some form and get some data rather than getting nothing and having it fail entirely. This would work fine for my agency, and be preferable to not being able to send purchase requests at all.

Right now, despite GA4 handling the requests fine, the FB requests using the same array are failing. I have no way to send the "items" array as it currently exists to GA4 (which again, handles it fine) without also sending it to FB and having everything fail. The only solution on my end is to stop sending an "items" array to GA4 entirely, or to have my code team rewrite code across a number of websites. Neither are particularly tenable.

@koconnor3
Copy link

koconnor3 commented Jun 27, 2022 via email

@billboyles
Copy link
Author

That's actually not a bad suggestion. Thanks!

facebook-github-bot pushed a commit that referenced this issue Apr 17, 2023
Summary:
Fixing issue #37 of the Issues@ Github repository #37

References Phase 1 fixes : https://docs.google.com/spreadsheets/d/1hNyHkqfdeWO_qkIfix2Gilriz28D_xkMCmk3nbnhVgM/edit#gid=0/

Parameters in the contents array changed which is causing issue in parsing. Removed title, brand and category.

Earlier parsing items array  [{"item_name" : 'Homestyle Huddle Wrap', "item_price" : 7.49, "quantity" : 1}] resulted in this:
"contents":[{ "title" : "Homestyle Huddle Wrap","item_price" : 7.49,"quantity" : 1}]

Now corrected
"contents":[{ "id" : "Homestyle Huddle Wrap","item_price" : 7.49,"quantity" : 1}]

Differential Revision: D44417088

fbshipit-source-id: 190d12ba6fc51ce753cf5881779c4d9303cc02b5
@skydivesunrise
Copy link

Hi, what would be the correct code today to get the correct values?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants