Bedrock: Pass through utm parameters on FxA referrals

Created on 26 Feb 2019  路  17Comments  路  Source: mozilla/bedrock

Description

Pass through utm parameters from upstream referrers when referring www.mozilla.org visitors to FxA signup form. Continue sending an entrypoint generated by mozilla.org. Bug with detailed specs.

Here's a complete URL, and I'll break it down.

`https://accounts.firefox.com/signup?service=sync&context=fx_desktop_v3&entrypoint=mozilla.org-globalnav&utm_source=desktop-snippet&utm_content=rel-esr&utm_medium=referral&utm_term=4242&utm_campaign=F100_4242_otherstuff_in_here

Breakdown:

?service=sync&context=fx_desktop_v3
Required by FxA server.
&entrypoint=mozilla.org-globalnav
This is the entrypoint as defined in FxA client metrics spec[0]. Where did the user enter from? From the global nav on mozilla.org. On mozilla.org, we should use a standard format (see other issue).

&utm_source=desktop-snippet&utm_content=rel-esr&utm_medium=referral&utm_term=4242&utm_campaign=F100_4242_otherstuff_in_here
These are all the standard UTM parameters that snippets and emails and other referrers send. We should validate these using the validation logic used by the FxA server, and if valid, we should pass them through to FxA so they end up in Amplitude, where we can use them to understand upstream referrers.

If there are not valid UTM parameters, we should add site-default utm parameters from Mozilla.org in the following format:

utm_content=[urlsafe content of CTA]&utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=[urlsafe category of CTA]

Here is an example from our current site:

utm_content=get-firefox-account&utm_source=www.mozilla.org&utm_medium=referral&utm_campaign=globalnav

Estimates (How much time in hours (up to 2), then in 1/2 day increments it will take each role to complete the work required to meet the Success Criteria established for this issue).

| Estimates | |
| ------------- | ------------- |
| TL = TeamLead | |
| PM = Program Manager | |
| Eng = Engineer | 12 |
| SEO | |
| ANA = Analytics | |
| DES = Design | |
| COPY | |


:yellow_heart: Success Criteria :yellow_heart:

For every referral point on the website, ensure...

  • [x] pre-existing utm parameters are sent on to FxA servers when referrals occur
  • [x] if no pre-existing url parameters are sent, use site standard utm parameters (those present now)
  • [x] ensure that the new specifications for entrypoint is included with every FxA referral
  • [ ] Is on every FxA CTA (including the nav)
  • [ ] Has been tested, unit tested, thoroughly to account for edge cases and/or bugs
  • [x] Doesn't clobber e.g. China repack server

Most helpful comment

There鈥檚 a lot of discussion and I may have missed something, but I think there鈥檚 a relatively non-complex solution.

The Firefox Accounts team already had a list of utm param regex validation rules that they apply on the server side https://mozilla.github.io/application-services/docs/accounts/metrics.html#descriptions-of-metrics-related-query-parameters

We should use these rules and validate them here on the client in bedrock. Doing so will likely eliminate any XSS risk, and would also ensure that we鈥檙e passing along valid referral data. If we don鈥檛 validate using these rules, then we鈥檇 risk losing data as invalid values aren鈥檛 passed along to amplitude.

All 17 comments

This is blocked only on final parameters. If a developer can find all the places needing changes, and stage the changes, then when final parameters are known, we can put them in place and launch.

We added a new card for putting the final parameters in place. This issue can focus on building the plumbing. Unblocking this.

utm_source:
Currently, any template on mozorg that passes a source value to any macro utilizing fxa_link_fragment will overwrite/add utm_source onto the URL. So mozorg will be getting the credit for those referrals regardless of where the user originally come from (ex: desktop-snippet). We should do a utm check to see if a source value is currently in place before adding our own.

Unfortunately, the value of the query params is not trusted and XSS is a risk. We have done validation regex in the past for data from AMO, the data for which was specifically formatted.

  • Is there a way to find out what utm_source values we can expect?
  • Can we specifically format all source values so we can do a regex check?
  • (Unfortunately, this is currently the only way we can validate which does make the team uncomfortable. We should flag this security issue.)

(per conversation with @pmac, @alexgibson, & @stephaniehobson)

utm_source:
Currently, any template on mozorg that passes a source value to any macro utilizing fxa_link_fragment

(ref: https://github.com/mozilla/bedrock/blob/c304c1ad7e7a3537c67cdb0d70c85bf6a4481781/bedrock/base/templates/macros.html#L304)

will overwrite/add utm_source onto the URL. So mozorg will be getting the credit for those referrals regardless of where the user originally come from (ex: desktop-snippet). We should do a utm check to see if a source value is currently in place before adding our own.

Question: Do we actually need to check to see if a utm_source value is in place, or can we simply check to see if the utm_source _key_ is present? And if we checked only for presence of the key, would we mitigate the XSS risk?

* Is there a way to find out what `utm_source` values we can expect?

If there is no other way forward, we could try to limit this pass-through behavior to channels where we know we have FxA marketing. It's not a lot, now. However, those channels are sure to multiply; we may only discover that they have multiplied when a campaign owner asks us how to look at the metrics for the campaign that just ended. (That would be unfortunate.)

* Can we specifically format all source values so we can do a regex check?

We don't have total control over source parameters at the moment of creation. They're still the product of very loose process; in fact, we're lucky when they are created at all. That said, valid sources don't tend to use a lot of ", (, < etc. So a regex that restricted sources to a list of urlsafe string characters might work, but are there alternatives to putting the burden of url validation out at the client, on individual pages? Is there any possibility of a single global validation of url parameters at request time? Could we use a library (e.g. Scrapy's w3lib ) instead of a home-rolled regex?

Question: Do we actually need to check to see if a utm_source value is in place, or can we simply check to see if the utm_source key is present? And if we checked only for presence of the key, would we mitigate the XSS risk?

_Afaik_, no. To truly mitigate the risk I believe we would need to do a check to see if it is signed to verify. I believe using regex to check for a format of parameters that we expect is the only form of validation we do currently, which is important but maybe there is something more we can do. It is something to look into.

Is there any possibility of a single global validation of url parameters at request time?

Agree that it would be nice to not put this burden on the client, but tbh I don't believe the JS burden is _too_ great compared to what we usually do (@alexgibson wdyt?). I think a global validation at request time is worth exploring, perhaps we could separate that into it's own issue. Agree we should definitely restrict the use to url-safe string characters.

Ideally, I would like to explore if it is at all possible for analytics to see the patterns of utm_source and to continue to allow pages to write to it. That way we do not need to worry about the trustworthiness of a query param. I am not sure if this is possible.

Question: Do we actually need to check to see if a utm_source value is in place, or can we simply check to see if the utm_source _key_ is present? And if we checked only for presence of the key, would we mitigate the XSS risk?

Does this mean that it might be sufficient to look for the presence of a utm_source parameter in the URL, and if it's there simply remove the utm_source=www.mozilla.org from the FxA URL? The risk is in putting the value from the URL in the DOM of the page via JS since the value is untrusted and could be malicious. But if we don't move any data into the page and simply look for the presence of the param and then remove something from the page that would be completely safe.

There鈥檚 a lot of discussion and I may have missed something, but I think there鈥檚 a relatively non-complex solution.

The Firefox Accounts team already had a list of utm param regex validation rules that they apply on the server side https://mozilla.github.io/application-services/docs/accounts/metrics.html#descriptions-of-metrics-related-query-parameters

We should use these rules and validate them here on the client in bedrock. Doing so will likely eliminate any XSS risk, and would also ensure that we鈥檙e passing along valid referral data. If we don鈥檛 validate using these rules, then we鈥檇 risk losing data as invalid values aren鈥檛 passed along to amplitude.

That is fantastic Alex! I did not know about that. Great solution. 馃挴

Closing this as the set up work was done. Inserting the parameters now that they are available the work to insert them is to be done in #7061

@amychurchwell - please an Estimate to this work.

Reopening issue to separate pull requests by concern.

@amychurchwell I updated the description of this issue.

The PR above has been merged, but there are still some remaining tasks and items that have not yet been covered:

  • Global navigation fxa cta button
  • Sign-in links
  • Email-first form
  • Write tests

These are detailed in https://github.com/mozilla/bedrock/issues/7169

@amychurchwell this issue ended up taking longer than we thought. Could you resize it? Was it a 21? Bigger?

@hoosteeno Follow up question. If a parameter is not present (for example: missing utm_content). Should we add our own utm_content=get-firefox-account? Or, if any UTMs are present in the URL should we not add any of ours?

@hoosteeno Follow up question. If a parameter is not present (for example: missing utm_content). Should we add our own utm_content=get-firefox-account? Or, if any UTMs are present in the URL should we not add any of ours?

@stephaniehobson sorry for the delay. If utm_* are present, let's not add any of our own. We do add missing ones on desktop downloads because all 4 (source/campaign/medium/content) are required by stub attribution, but there is no such requirement in FxA, and adding them just muddies the water.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexgibson picture alexgibson  路  8Comments

hoosteeno picture hoosteeno  路  9Comments

hoosteeno picture hoosteeno  路  11Comments

ejregithub picture ejregithub  路  10Comments

alexgibson picture alexgibson  路  14Comments