PL Launch 2023 - Show default homepage hero banner to int'l audiences - #51356
Conversation
megcrenshaw
left a comment
There was a problem hiding this comment.
I'm confused about the product requirement –– do we want to show the page for English users or for users inside the US? It looks like this PR will show the banner for any English user, including English users in, say, India or Australia.
|
Good question Meg. The goal is to show the PL banner just to United States users. Is it possible to do that instead of relying on language to try to capture that? |
I don't think we have the functionality for the homepage.json banners to show based off of geolocation (yet?) — I'll look into it. |
|
For more context — this is what we did last year for the CSA launch hero banner that had similar audience requirements (Brendan helped me pair on this): |
|
Looks like this is where we set the language config: code-dot-org/pegasus/src/homepage.rb Lines 31 to 32 in 062d9ef I believe we could use a similar pattern for country, but it's not currently configured. Depending on how high priority this is, one of us could implement this functionality for, Kelby, you to use. (Kelby, I'm sure you could get this working too, but I'm guessing learning Ruby wasn't part of the job description 😅 .) |
|
@megcrenshaw thank you for looking into this. This is high priority as we are sending lots of traffic to pages that don't make any sense for them. Could you send some time today or tomorrow helping Kelby to get this working? |
I just tried that in this commit but it wasn't working 😅 maybe I missed something though? |
|
@dmcavoy Yep, on it! Want to try the following? Then try If that doesn't work, let me know and we can either pair on it or I can take a deeper look solo. Thanks, Kelby, for starting on this! |
| # If the banner is shown internationally don't show in the US. | ||
| # If the banner is not shown internationally, show in the US. | ||
| location = Geocoder.search(request.ip)&.first | ||
| in_us = location&.country_code.to_s.casecmp?('us') | ||
| next unless banner["showInternationally"] ^ in_us |
There was a problem hiding this comment.
questions:
- how often is request.ip set? is it as reliable as user.current_sign_in_ip?
- does this codepath work (no errors) when request.ip is nil?
- in the case where request.ip is nil, are we ok with showing only outside us?
- I'm not sure about taking away the option to display banners globally. isn't this something we'll want to do for HOC?
There was a problem hiding this comment.
Good questions.
1-2) We can't use current_sign_in_ip because the user may not be signed in and we're on pegasus. But I don't know how often request.ip is set.
I went to this thread https://codedotorg.slack.com/archives/C0T0PNTM3/p1600671794018400 and it looks like the most established pattern is to be using request.country instead of request.location.country_code. @kelbyhawn thoughts about trying the following instead?
# remove location line
in_us = request.country.to_s.casecmp?('us')
next unless banner["showInternationally"] ^ in_us
- @dmcavoy do you know preferred behavior when we don't know the user's country?
- There are three options with the
showInternationallyflag:
false–– only show in the UStrue–– only show outside of the US- no flag –– show everywhere
There was a problem hiding this comment.
- There are three options with the
showInternationallyflag:
false–– only show in the UStrue–– only show outside of the US- no flag –– show everywhere
oh interesting! how is "show everywhere" implemented? the behavior I'm seeing makes me think that "no flag" will behave like false:
irb(main):001:0> nil ^ false
=> false
irb(main):002:0> nil ^ true
=> true
There was a problem hiding this comment.
If we don't know a users country I think it would be good to default to the US banner for now as thats our primary audience
There was a problem hiding this comment.
Oh yikes, Dave! Good call –– we tested this manually, but I think didn't cover all the cases.
@kelbyhawn I think either (a) we pair again to get this working, or (b) I pull down the branch and make the commit myself. Do you have a preference?
There was a problem hiding this comment.
@megcrenshaw , given the need for thorough validation on our side, I'd encourage you to pull down the branch and make any changes needed, rather than going through Kelby for each update.
There was a problem hiding this comment.
I might go ahead and add unit tests for this part too –– it will help me believe it's working
There was a problem hiding this comment.
That works for me @megcrenshaw, and thanks @davidsbailey for reviewing this!
156556d to
e4a522f
Compare
|
Just updated this file with refactored logic and some tests –– @breville and @davidsbailey would love for y'all to take a look when you're able! @kelbyhawn tagging you just to give you an update on progress. |
| # If the banner has an array of languages, then the current language must be one of them. | ||
| next if banner["languages"] && !banner["languages"].include?(request.language) | ||
|
|
||
| # If the banner has an showInternationally flag, |
There was a problem hiding this comment.
Not blocking, very minor typo: an should be a.
davidsbailey
left a comment
There was a problem hiding this comment.
Super glad to see this go out with test coverage. ⚓ ship it!
| banner = Homepage.get_announcement_for_page("homepage", @request) | ||
| assert_equal("show-everywhere", banner[:id]) | ||
| end | ||
| end |
There was a problem hiding this comment.
these tests are awesome, thanks for adding these!
I feel bad even mentioning this, but as part of the effort to separate dashboard from pegasus, we are trying to avoid cross-project dependencies like this, and so in the future any tests on pegasus pages should go in pegasus/test. this is the ideal dependency graph:
this is my bad for not setting up linting rules preventing this kind of cross-project dependency, which I have been meaning to do for some time now. so for now I'm just going to ask that any additional tests for pegasus code be located in pegasus/test. 🙏
There was a problem hiding this comment.
Oh good call –– @kelbyhawn can I go ahead and update this? I hate shipping code that needs a refactor 😅
There was a problem hiding this comment.
@megcrenshaw yes, absolutely! How much time do you think this'll add before it can be merged? (Only asking due to the AI banner dependency 🙃)
There was a problem hiding this comment.
Give me like 15 minutes –– I have it moved with tests passing, but cleaning up a few things. Then it needs to go through drone ... so end of day your time
There was a problem hiding this comment.
Just pushed new stuff. @davidsbailey do you want to take another look? It's my first rodeo writing a pegasus unit test, but the test structure didn't change. Perhaps if there are requested refactors, I can tackle them in a separate PR
| # If the banner has a showInternationally flag, | ||
| # only show if exactly one of showInternationally or location_unknown_or_usa are true | ||
| location_unknown_or_usa = request.country.nil? || request.country.to_s.casecmp?('us') | ||
| next if banner.key?("showInternationally") && !(banner["showInternationally"] ^ location_unknown_or_usa) |
davidsbailey
left a comment
There was a problem hiding this comment.
thanks for moving these tests Meg! LGTM once drone passes.
I do have one question: which bucket do we fall into when viewing these pages in local development? I don't think the answer should block this PR, but worth considering what we want the local experience to be.
|
@megcrenshaw feel free to merge this w/o me when it's ready (unless it's better practice that I do it?) |
Ah, good call! It's ready. I'll merge 🥳 |
@davidsbailey great question. When Kelby and I tested this locally, the |
my input would just be to pick what you want the behavior to be, and have your code provide that behavior when the country code is |
|
it sounds like this is time-sensitive, so feel free to do in a follow-up PR. |
|
@kelbyhawn do you want the local setup to behave like the US? If so, I'll create a followup PR to address that. |
@megcrenshaw yes, that would be great thanks! |

Show the default homepage hero banner to international audiences and the PL superhero banner to US only.
Asana task: https://app.asana.com/0/0/1204402039772899
Related PR:
Testing story
[from Meg] The
homepage.rbfile currently has no tests. To convince myself that theshowInternationallyflag was working as expected, I used the announcements test file for inspiration.I had three attempted testing strategies and landed on the last one:
Homepage.class_variable_set(:@@announcements_data, {...}). But that approach meant that the vast majority of the test file was hard-to-parse JSONs, or hard-to-read updates to a single JSON.showInternationallyflags, and our current banner configuration returns the very first banner it finds:code-dot-org/pegasus/src/homepage.rb
Lines 34 to 35 in 0cc37cc
showInternationallyflag configurations ––true,false, and no flag. I don't love that there is quite a bit of repeated code for each JSON, but I do think it is more readable than the approach in (1).Links
[from Meg] Asked Platform about best practices for querying location here https://codedotorg.slack.com/archives/CFTFD6BPV/p1681909723548929?thread_ts=1680634885.139079&cid=CFTFD6BPV