Skip to content

submit course / program as product_of_interest if the field is on the form#3231

Merged
gumaerc merged 10 commits into
mainfrom
cg/hubspot-product-of-interest
Apr 23, 2026
Merged

submit course / program as product_of_interest if the field is on the form#3231
gumaerc merged 10 commits into
mainfrom
cg/hubspot-product-of-interest

Conversation

@gumaerc
Copy link
Copy Markdown
Contributor

@gumaerc gumaerc commented Apr 21, 2026

What are the relevant tickets?

Part of https://github.com/mitodl/hq/issues/10939

Description (What does it do?)

This PR follows up on the work of #3216. Now that we can push up custom contact properties into HubSpot. If the product_of_interest field exists on the form, the Stay Updated dialog / form will now try and submit the current product's title along with the form as the product of interest.

How can this be tested?

  • Ensure that you have access to HubSpot configured and you have set the following variables in your env:
    • MITOL_HUBSPOT_API_PRIVATE_TOKEN in backend.local.env (get from RC if you need it)
    • NEXT_PUBLIC_STAY_UPDATED_HUBSPOT_FORM_ID in frontend.local.env (use f201f3af-c2c0-4b7d-b297-ddbb75912cc1 if you're using RC credentials)
    • RECAPTCHA_SITE_KEY / RECAPTCHA_SECRET_KEY in shared.local.env (example defaults in backend.local.example.env, or create your own at https://www.google.com/recaptcha/admin/create)
  • Ensure that you have MITx Online set up and configured to connect with MIT Learn as described in the README and have the Posthog feature flag mitxonline-product-pages enabled
  • Make sure you have a program / courses set up in MITx Online with include_in_learn_catalog enabled and that you have run backpopulate_mitxonline_courses at least once
  • Populate the product_of_interest field using the following management command:
docker compose exec web uv run python manage.py update_hubspot_contact_property_choices product_of_interest \
  --learning-resource-field title \
  --option-value-field readable_id \
  --resource-type course \
  --resource-type program \
  --resource-order-by title \
  --resource-distinct \
  --property-label "Product of Interest" \
  --property-field-type checkbox
  • Visit the program page at /programs/program-readable-id
  • Ensure that the Stay Updated button is displaying properly in the banner
  • Click the button and you should be presented with the dialog
  • Fill out the details and click "Inform Me"
  • Verify that you see the success message and can click "Done" to dismiss the dialog
  • If you have access, log into the HubSpot dashboard and view your submission to ensure it came in correctly, including the actual "product of interest" from the page you submitted the form from

Copilot AI review requested due to automatic review settings April 21, 2026 21:37
@gumaerc gumaerc added the Needs Review An open Pull Request that is ready for review label Apr 21, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 21, 2026

OpenAPI Changes

2 changes: 0 error, 1 warning, 1 info

View full changelog

Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the “Stay Updated” HubSpot submission flow on product pages so that, when the HubSpot form includes a product_of_interest field, the current product’s title is submitted as that field’s value.

Changes:

  • Pass the current product title into StayUpdatedModal when opening it from ProductPageTemplate.
  • Add logic in StayUpdatedModal to look up a matching product_of_interest option and include it in the submission payload.
  • Add/adjust frontend tests to assert the modal invocation args and the submitted HubSpot payload.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
frontends/main/src/app-pages/ProductPages/StayUpdatedModal.tsx Adds productTitle prop handling and attempts to resolve/submit product_of_interest from the HubSpot form definition.
frontends/main/src/app-pages/ProductPages/StayUpdatedModal.test.tsx Adds tests asserting product_of_interest is included/omitted in the HubSpot submit payload.
frontends/main/src/app-pages/ProductPages/ProductPageTemplate.tsx Passes title into StayUpdatedModal when opening the modal.
frontends/main/src/app-pages/ProductPages/ProductPageTemplate.test.tsx Updates expectations to assert NiceModal.show receives productTitle.

return undefined
}

const productOfInterestField = hubspotForm?.fieldGroups
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

useHubspotFormDetail returns the generated HubspotFormDefinition shape which uses field_groups (snake_case). findProductOfInterestValue only inspects hubspotForm.fieldGroups, so in production it will never find the product_of_interest field and the value won't be submitted. Update this lookup to handle the actual response shape (e.g., prefer hubspotForm.fieldGroups ?? hubspotForm.field_groups when flattening field groups).

Suggested change
const productOfInterestField = hubspotForm?.fieldGroups
const fieldGroups = hubspotForm?.fieldGroups ?? hubspotForm?.field_groups
const productOfInterestField = fieldGroups

Copilot uses AI. Check for mistakes.
Comment on lines +170 to +188
setupApis({
fieldGroups: [
{
fields: [
{
name: "product_of_interest",
label: "Product of Interest",
field_type: "multiple_checkboxes",
options: [
{
label: TEST_PRODUCT_TITLE,
value: TEST_PRODUCT_VALUE,
},
],
},
],
},
],
})
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

These new tests build the mocked HubSpot form using fieldGroups, but the real API factory/response uses field_groups (snake_case). That means the test can pass even though the production code won’t find the field. Update the overrides to use field_groups (and nested fields/options as appropriate) so the test exercises the real response shape and catches regressions.

Copilot uses AI. Check for mistakes.
@shanbady shanbady self-assigned this Apr 22, 2026
@gumaerc gumaerc force-pushed the cg/hubspot-product-of-interest branch from c52e7f6 to fd730ae Compare April 22, 2026 15:05
Comment thread frontends/main/src/app-pages/ProductPages/StayUpdatedModal.tsx Outdated
@gumaerc gumaerc changed the title submit title as product_of_interest if the field is on the form submit course / program as product_of_interest if the field is on the form Apr 22, 2026
@gumaerc gumaerc force-pushed the cg/hubspot-product-of-interest branch from 8c0358f to f7b7416 Compare April 22, 2026 15:47
Comment thread ol_hubspot/management/commands/update_hubspot_contact_property_choices.py Outdated
@shanbady shanbady removed their assignment Apr 22, 2026
@ChristopherChudzicki ChristopherChudzicki self-assigned this Apr 23, 2026
gumaerc and others added 5 commits April 23, 2026 11:16
…ble_id as the value for these options

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
@gumaerc gumaerc force-pushed the cg/hubspot-product-of-interest branch from 6aa68a5 to aedcbc1 Compare April 23, 2026 15:16
Copy link
Copy Markdown
Contributor

@ChristopherChudzicki ChristopherChudzicki left a comment

Choose a reason for hiding this comment

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

👍

I left a suggestion about the management command args.

Additionally... Using readable_id as the value is safe within mitxonline, but there are duplicates across different ETL sources. We'll have to cross this bridge when it comes to course/program URLs eventually, I suspect.

But it's one reason I might suggest having a MANDATORY filter on the management command for ETL source or platform or something. Plus, we don't need 2700 free ocw courses in hubspot.

The duplicates, btw, are

readable_id     duplication_count       etl_sources
MITx+0.SolveX   2                       mit_edx, oll
MITx+11.154x    2                       mit_edx, oll
MITx+11.155x    2                       mit_edx, oll
MITx+11.550x    2                       mit_edx, oll
MITx+15.480x    2                       mit_edx, oll
MITx+15.481x    2                       mit_edx, oll
MITx+15.482x    2                       mit_edx, oll
MITx+22.011x    2                       mit_edx, oll

(that's MITx on edx.com and open learning library).

Comment thread frontends/main/src/app-pages/ProductPages/StayUpdatedModal.tsx Outdated
Comment thread ol_hubspot/management/commands/update_hubspot_contact_property_choices.py Outdated
Comment thread frontends/main/src/app-pages/ProductPages/CoursePage.tsx Outdated
gumaerc and others added 5 commits April 23, 2026 15:16
@gumaerc gumaerc merged commit f0bff07 into main Apr 23, 2026
14 checks passed
@gumaerc gumaerc deleted the cg/hubspot-product-of-interest branch April 23, 2026 20:07
This was referenced Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs Review An open Pull Request that is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants