Skip to content

Commit 5441573

Browse files
Jiaming Youmeta-codesync[bot]
authored andcommitted
Add Event.referrer_url and auto-populate from CAPI ParamBuilder
Summary: # Problem `com.facebook.capi.sdk:capi-param-builder` 1.3.0 (D106968654) exposes `ParamBuilder.getReferrerUrl()`, and the Java SDK's `Preference` already has the `is_referrer_url_allowed` gate. What is still missing is (1) a `referrer_url` field on `Event` to land the value in, and (2) the wiring in `Event.applyParamBuilderDefaults()` that consults the ParamBuilder when `setRequestContext(...)` is used. This mirrors the Node.js change in D106967695, the PHP change in D106908330, the Ruby change in D106704554, and the Python change in D106700660. # Solution Add `referrer_url` to `Event`, following the shape of `event_source_url`: - New `SerializedName("referrer_url")` field `referrerUrl` (gson serializes it on the wire automatically; null is omitted). - `referrerUrl` appended as the last parameter of the all-args constructor (with `param` doc + assignment), matching how every prior field was added to this constructor — e.g. `originalEventData` / `attributionData` were appended in place in D59667901. This is source- and binary-incompatible for callers of the positional `new Event(...)` constructor, consistent with the SDK's established pattern of growing that constructor per release. Callers using the fluent `new Event()` builder are unaffected, and no in-repo caller uses the positional form (all 42 sites use the fluent builder). - Fluent `referrerUrl(String)`, getter `getReferrerUrl()`, and plain `setReferrerUrl(...)`, adjacent to the `eventSourceUrl` accessors. - `equals`, `hashCode`, and `toString` updated to include the new field. Extend `Event.applyParamBuilderDefaults()` so that after the `event_source_url` handling it also reads `paramBuilder.getReferrerUrl()` and assigns it to the event's `referrerUrl` when: - `preference.isReferrerUrlAllowed()` is `true` (default), AND - `referrerUrl` is currently null or empty (caller-supplied values always win, matching the precedence rule for fbc/fbp/event_source_url), AND - the builder returned a non-empty URL. As with the fbc/fbp/event_source_url handling, this is wired and unit-tested via a mocked `ParamBuilder` but is a runtime no-op until the deferred `processRequestFromContext` call in `setRequestContext` is re-enabled (see the NOTE there) — kept in lock-step with the other fields rather than changing that behavior here. Differential Revision: D106972893 fbshipit-source-id: 70f9ad280ca530c00a489d14a4f65b096b904014
1 parent 21cf543 commit 5441573

2 files changed

Lines changed: 105 additions & 4 deletions

File tree

src/main/java/com/facebook/ads/sdk/serverside/Event.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public class Event {
3535
@SerializedName("event_source_url")
3636
private String eventSourceUrl = null;
3737

38+
@SerializedName("referrer_url")
39+
private String referrerUrl = null;
40+
3841
@SerializedName("opt_out")
3942
private Boolean optOut = null;
4043

@@ -106,12 +109,13 @@ public Event() {
106109
* @param messagingChannel indicated the messaging channel used.
107110
* *@param originalEventData indicated the original event data used for attribution passback or generalized value optimization(GVO).
108111
* @param attributionData indicated the attribution data used for attribution passback event to optimize the performance.
112+
* @param referrerUrl referrer URL of the browser request that triggered the event
109113
*/
110114
public Event(String eventName, Long eventTime, String eventSourceUrl, Boolean optOut,
111115
String eventId, UserData userData, CustomData customData, String[] dataProcessingOptions,
112116
Integer dataProcessingOptionsCountry, Integer dataProcessingOptionsState, ActionSource actionSource, AppData appData,
113-
String advancedMeasurementTable, MessagingChannel messagingChannel, OriginalEventData originalEventData,
114-
AttributionData attributionData) {
117+
String advancedMeasurementTable, MessagingChannel messagingChannel, OriginalEventData originalEventData,
118+
AttributionData attributionData, String referrerUrl) {
115119
this.eventName = eventName;
116120
this.eventTime = eventTime;
117121
this.eventSourceUrl = eventSourceUrl;
@@ -128,6 +132,7 @@ public Event(String eventName, Long eventTime, String eventSourceUrl, Boolean op
128132
this.messagingChannel = messagingChannel;
129133
this.originalEventData = originalEventData;
130134
this.attributionData = attributionData;
135+
this.referrerUrl = referrerUrl;
131136
}
132137

133138
/**
@@ -217,6 +222,35 @@ public void setEventSourceUrl(String eventSourceUrl) {
217222
this.eventSourceUrl = eventSourceUrl;
218223
}
219224

225+
/**
226+
* Set referrer URL of the browser request that triggered the event.
227+
*
228+
* @param referrerUrl referrer URL of the browser request that triggered the event
229+
* @return Event
230+
*/
231+
public Event referrerUrl(String referrerUrl) {
232+
this.referrerUrl = referrerUrl;
233+
return this;
234+
}
235+
236+
/**
237+
* Get referrer URL of the browser request that triggered the event.
238+
*
239+
* @return referrerUrl
240+
*/
241+
public String getReferrerUrl() {
242+
return referrerUrl;
243+
}
244+
245+
/**
246+
* Set referrer URL of the browser request that triggered the event.
247+
*
248+
* @param referrerUrl referrer URL of the browser request that triggered the event
249+
*/
250+
public void setReferrerUrl(String referrerUrl) {
251+
this.referrerUrl = referrerUrl;
252+
}
253+
220254
/**
221255
* Set flag that indicates we should not use this event for ads delivery optimization. If set to
222256
* true, we only use the event for attribution.
@@ -674,6 +708,13 @@ public Event setRequestContext(Object context, Preference preference) {
674708
&& builderEventSourceUrl != null && !builderEventSourceUrl.isEmpty()) {
675709
this.eventSourceUrl = builderEventSourceUrl;
676710
}
711+
712+
String builderReferrerUrl = this.paramBuilder.getReferrerUrl();
713+
if (Boolean.TRUE.equals(this.preference.isReferrerUrlAllowed())
714+
&& (this.referrerUrl == null || this.referrerUrl.isEmpty())
715+
&& builderReferrerUrl != null && !builderReferrerUrl.isEmpty()) {
716+
this.referrerUrl = builderReferrerUrl;
717+
}
677718
}
678719

679720
/**
@@ -725,13 +766,14 @@ public boolean equals(Object o) {
725766
&& Objects.equals(this.dataProcessingOptionsState, event.dataProcessingOptionsState)
726767
&& Objects.equals(this.messagingChannel, event.messagingChannel)
727768
&& Objects.equals(this.originalEventData, event.originalEventData)
728-
&& Objects.equals(this.attributionData, event.attributionData);
769+
&& Objects.equals(this.attributionData, event.attributionData)
770+
&& Objects.equals(this.referrerUrl, event.referrerUrl);
729771
}
730772

731773
@Override
732774
public int hashCode() {
733775
return Objects.hash(
734-
eventName, eventTime, eventSourceUrl, optOut, eventId, userData, customData, dataProcessingOptions, dataProcessingOptionsCountry, dataProcessingOptionsState , messagingChannel, originalEventData, attributionData);
776+
eventName, eventTime, eventSourceUrl, optOut, eventId, userData, customData, dataProcessingOptions, dataProcessingOptionsCountry, dataProcessingOptionsState , messagingChannel, originalEventData, attributionData, referrerUrl);
735777
}
736778

737779
@Override
@@ -742,6 +784,7 @@ public String toString() {
742784
sb.append(" eventName: ").append(toIndentedString(eventName)).append("\n");
743785
sb.append(" eventTime: ").append(toIndentedString(eventTime)).append("\n");
744786
sb.append(" eventSourceUrl: ").append(toIndentedString(eventSourceUrl)).append("\n");
787+
sb.append(" referrerUrl: ").append(toIndentedString(referrerUrl)).append("\n");
745788
sb.append(" optOut: ").append(toIndentedString(optOut)).append("\n");
746789
sb.append(" eventId: ").append(toIndentedString(eventId)).append("\n");
747790
sb.append(" userData: ").append(toIndentedString(userData)).append("\n");

src/test/java/com/facebook/ads/sdk/serverside/EventRequestContextTest.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ public void testPreferenceAllFalseSuppressesEveryAutoField() {
205205
when(pb.getFbc()).thenReturn("XX");
206206
when(pb.getFbp()).thenReturn("YY");
207207
when(pb.getEventSourceUrl()).thenReturn("https://shop.example.com/cart");
208+
when(pb.getReferrerUrl()).thenReturn("https://referrer.example.com/");
208209
})) {
209210
Preference pref = new Preference(false, false, false, false, false);
210211
Event event = new Event()
@@ -220,6 +221,7 @@ public void testPreferenceAllFalseSuppressesEveryAutoField() {
220221
assertNull(ud.getFbp());
221222
}
222223
assertNull(event.getEventSourceUrl());
224+
assertNull(event.getReferrerUrl());
223225
}
224226
}
225227

@@ -279,6 +281,62 @@ public void testPreferenceGatesEventSourceUrl() {
279281
}
280282
}
281283

284+
// ----------------------------------------------------------------
285+
// referrer_url auto-population (mocked ParamBuilder)
286+
// ----------------------------------------------------------------
287+
288+
@Test
289+
public void testAutoPopulatesReferrerUrl() {
290+
try (MockedConstruction<ParamBuilder> mocked =
291+
mockConstruction(ParamBuilder.class, (pb, ctx) -> {
292+
when(pb.getReferrerUrl()).thenReturn("https://google.com/search?q=foo");
293+
})) {
294+
Event event = new Event()
295+
.eventName("PageView")
296+
.eventTime(1700000070L)
297+
.setRequestContext(new Object());
298+
299+
event.applyParamBuilderDefaults();
300+
assertEquals("https://google.com/search?q=foo", event.getReferrerUrl());
301+
}
302+
}
303+
304+
@Test
305+
public void testCallerSuppliedReferrerUrlTakesPrecedence() {
306+
try (MockedConstruction<ParamBuilder> mocked =
307+
mockConstruction(ParamBuilder.class, (pb, ctx) -> {
308+
when(pb.getReferrerUrl()).thenReturn("https://from-builder/");
309+
})) {
310+
Event event = new Event()
311+
.eventName("Lead")
312+
.eventTime(1700000071L)
313+
.referrerUrl("https://from-caller/")
314+
.setRequestContext(new Object());
315+
316+
event.applyParamBuilderDefaults();
317+
assertEquals("https://from-caller/", event.getReferrerUrl());
318+
}
319+
}
320+
321+
@Test
322+
public void testPreferenceGatesReferrerUrl() {
323+
try (MockedConstruction<ParamBuilder> mocked =
324+
mockConstruction(ParamBuilder.class, (pb, ctx) -> {
325+
when(pb.getFbc()).thenReturn("WITHFBC");
326+
when(pb.getReferrerUrl()).thenReturn("https://from-builder/");
327+
})) {
328+
Preference pref = new Preference(true, true, true, false, true);
329+
Event event = new Event()
330+
.eventName("PageView")
331+
.eventTime(1700000072L)
332+
.setRequestContext(new Object(), pref);
333+
334+
event.applyParamBuilderDefaults();
335+
assertEquals("WITHFBC", event.getUserData().getFbc());
336+
assertNull(event.getReferrerUrl());
337+
}
338+
}
339+
282340
@Test
283341
public void testOrderIndependentUserDataBeforeRequestContext() {
284342
try (MockedConstruction<ParamBuilder> mocked =

0 commit comments

Comments
 (0)