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

Sketch in last-touch attribution #11

Merged
merged 5 commits into from
Sep 23, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions api.bs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,11 @@ navigator.privateAttribution.measureConversion({

// the number of buckets in the histogram
histogramSize: 20,
// the amount of privacy budget to use
epsilon: 1,

// the attribution logic to use
logic: "last-touch",
// the value to assign to the histogram index of the impression
value: 3,

Expand All @@ -492,9 +496,9 @@ navigator.privateAttribution.measureConversion({
<xmp class=idl>
dictionary PrivateAttributionConversionOptions {
required DOMString aggregator;
double epsilon = 1.0;

required unsigned long histogramSize;
double epsilon = 1.0;

PrivateAttributionLogic logic = "last-touch";
unsigned long value = 1;
Expand Down Expand Up @@ -613,15 +617,95 @@ the last (most recent) impression that matches the [[#logic-matching|common matc
The entire [=conversion value=] (up to the maximum imposed by the [[#dp-budget|privacy budget]])
is allocated to the histogram bucket that was saved with the impression.

Last touch attribution does not select any impression
that was saved during a week
that does not have sufficient [=privacy budget=].
Comment on lines +662 to +664
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had been assuming we could report partial conversion value if there is insufficient but non-zero privacy budget. Since the privacy budget is likely to be chosen by the browser (and may vary between browsers and over time), the conversion site doesn't necessarily know the available budget.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a preference for avoiding that sort of thing, at least until we have discussed it. It might be worth opening an issue to track that though.

If impressions match from a week
that does not have enough [=privacy budget=],
impressions are not matched for any preceding weeks.
That is, once a week has a matching impression
and insufficient budget,
the process will set a value of zero for all histogram buckets.

To <dfn ignore>fill a histogram using last-touch attribution</dfn>,
given |options|:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method of writing code is super, super annoying. This is far from being ready, but it has the bones that I think we need.

martinthomson marked this conversation as resolved.
Show resolved Hide resolved

1. Initialize |impression| to a null value.

1. Initialize |value| to |options|.|value|.
martinthomson marked this conversation as resolved.
Show resolved Hide resolved

1. Let |now| be the current time.<!-- TODO: cite HRTIME spec -->

1. For each |week| starting from the current week
to the oldest week supported by the [=user agent=]:
Comment on lines +681 to +682
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should define somewhere what a week is. Presumably UTC, but need to choose Sunday or Monday.


1. Let |impressions| be the result of invoking [=common matching logic=]
with |options|, |week|, and |now|.

1. If |impressions| is not empty:

1. Retain the value of |week|.

1. Set |impression| to the value in |impressions|
with the most recent |impression|.timestamp.
<!-- TODO define a type for stored impressions -->
Comment on lines +691 to +693
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make the keys in https://private-attribution.github.io/api/#impression-store-contents linkable, at the cost of the simpledef markup getting even uglier. I tested <dfn lt=stored-timestamp>Timestamp</dfn> before removing it because it was so ugly. Do you have a different kind of definition in mind? Maybe change it to a <dl>?

In the case of major clock adjustments, it is possible that the store could have impressions in the future. Is it worth discussing this case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The links we can work out later.

The local machine won't have any issue with that sort of time skew. I hope. (Modulo time adjustments....)


1. Exit the loop.

1. If |impression| is null, let |budgetOk| be false.

1. Otherwise, let |budgetOk| be the result of [=deduct privacy budget=]
with |week| and |options|.{{PrivateAttributionConversionOptions/epsilon}}.

1. If |budgetOk| is false, set |value| to 0.

1. If |impression|.|histogramIndex|
is |options|.{{PrivateAttributionConversionOptions/histogramSize}} or greater,
set |value| to 0.

### Common Matching Logic ### {#logic-matching}
1. If |value| is not 0, set |index|
to |impression|.{{PrivateAttributionImpressionOptions/histogramIndex}}.

1. Otherwise, set |index| to 0.

1. Return a histogram containing |options|.{{PrivateAttributionConversionOptions/histogramSize}} values,
with a value of |value| at an index of |index|
and a value of zero at all other indices.


### Common Impression Matching Logic ### {#logic-matching}

TODO specify how to match using "lookbackDays", "ads" and "impressionSites".

Discuss "infinite" lookbackDays. Clarify when it apples. When field is missing? Zero?

<dfn>ad identifier</dfn>

To perform <dfn>common matching logic</dfn>,
given |options|, |week|, and [=moment=] |now|:

1. If number of days since the end of |week| exceeds |lookbackDays|,
return an empty set.

1. Initialize |matching| to an empty set.

1. For each |impression| in the saved impressions for the |week|:

1. If |now| - |lookbackDays| is after |impression|.timestamp,
continue the loop.

1. If |options|.{{PrivateAttributionConversionOptions/ads}}
does not contain |impression|.ad,
continue the loop.

1. If |options|.{{PrivateAttributionConversionOptions/impressionSites}}
does not contain |impression|.source,
martinthomson marked this conversation as resolved.
Show resolved Hide resolved
continue the loop.

1. Add |impression| to |matching|.

1. Return |matching|.


## User control and visibility ## {#user-control}

Expand Down Expand Up @@ -930,6 +1014,10 @@ whether their request for a [=conversion report=] has caused
a safety limit to be exceeded.


### Privacy Budget Deduction ### {#dp-deduction}

To <dfn>deduct privacy budget</dfn>, do this...



## Differential Privacy Mechanisms ## {#dp-mechanism}
Expand Down
Loading