Skip to content

Commit 75f1c8f

Browse files
fix(SUPPORT-15409): handle new Facebook API breakdown format in values array
Facebook's November 2025 API changes put breakdown fields as siblings of 'value' and 'end_time' in the values array, instead of nesting them inside the 'value' field as a map. This caused empty key1/key2 columns in the output. Changes: - Add extract-breakdown-fields fn to detect sibling breakdown fields - Update flatten-array to pass breakdown fields to flatten-array-value - Update flatten-array-value to accept and merge breakdown fields - Backward compatible: existing queries without breakdown siblings produce identical output Co-Authored-By: unknown <>
1 parent 21bff5c commit 75f1c8f

1 file changed

Lines changed: 35 additions & 7 deletions

File tree

src/keboola/facebook/api/parser.clj

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,22 @@
5353
object-value)
5454
:else (list {:key1 key1 :key2 "" :value object-value})))
5555

56-
(defn flatten-array-value [item end_time]
57-
(map
58-
#(assoc % :end_time end_time)
59-
(cond
60-
(map? item) (mapcat (fn [[key1 val]] (flatten-value-object (name key1) val)) item)
61-
:else (list {:key1 "" :key2 "" :value item}))))
56+
(defn flatten-array-value
57+
"Flattens a single values array entry into key1/key2/value rows.
58+
Supports both old format (value is a map) and new Facebook API breakdown
59+
format where breakdown fields are siblings of value and end_time."
60+
([item end_time]
61+
(flatten-array-value item end_time {}))
62+
([item end_time breakdown-fields]
63+
(map
64+
#(merge % {:end_time end_time} breakdown-fields)
65+
(cond
66+
(map? item) (mapcat (fn [[key1 val]] (flatten-value-object (name key1) val)) item)
67+
:else (list {:key1 (or (first (vals breakdown-fields)) "")
68+
:key2 (if (> (count breakdown-fields) 1)
69+
(second (vals breakdown-fields))
70+
"")
71+
:value item})))))
6272

6373
(def ads-action-stats-types #{:actions :properties :conversion_values
6474
:action_values :canvas_component_avg_pct_view
@@ -73,12 +83,30 @@
7383

7484
(def serialized-lists-types #{:issues_info :frequency_control_specs})
7585

86+
(defn extract-breakdown-fields
87+
"Extracts breakdown fields from a values array entry.
88+
Breakdown fields are any fields that are not :value or :end_time.
89+
Returns a map of breakdown field names (as strings) to their values."
90+
[entry]
91+
(let [known-keys #{:value :end_time}]
92+
(into {} (keep (fn [[k v]]
93+
(when-not (known-keys k)
94+
[(name k) (str v)]))
95+
entry))))
96+
7697
(defn flatten-array
7798
"flattens array of object with same structure prefixing its keys with array-name
7899
returns list of key-value pairs"
79100
[array array-name]
80101
(cond (= array-name :values)
81-
(mapcat #(flatten-array-value (:value %) (:end_time %)) array)
102+
(mapcat #(let [breakdowns (extract-breakdown-fields %)
103+
breakdown-keys (sort (keys breakdowns))
104+
key1 (if (seq breakdown-keys) (get breakdowns (first breakdown-keys)) nil)
105+
key2 (if (> (count breakdown-keys) 1) (get breakdowns (second breakdown-keys)) nil)
106+
breakdown-map (cond-> {}
107+
key1 (assoc :key1 key1)
108+
key2 (assoc :key2 key2))]
109+
(flatten-array-value (:value %) (:end_time %) breakdown-map)) array)
82110
(some? (ads-action-stats-types array-name))
83111
(map #(assoc % :ads_action_name (name array-name)) array)
84112
(some? (serialized-lists-types array-name))

0 commit comments

Comments
 (0)