Custom Service Agreements


Customers wanted their users to accept custom terms of service and privacy policy information for their team.


Agreement: A prompt like a terms of service or privacy policy that users have to accept to proceed.

Historical Agreement: A past agreement of a type that has been replaced by a newer agreement

Type: Differentiating the type of agreement being made

Acceptance: A record of users accepting the agreement.



  • Needed to be able to track users' acceptance of agreements for compliance.
  • When a policy was updated we needed to re-prompt the user to accept the new agreement.
  • Users should not be re-prompted for agreements they've already accepted.
  • Our customer success team had to be able to easily create new terms of service where necessary.

Existing Functionality

Our system already had concepts like "Terms of Service" and "Privacy Policy", but they were hard coded into the front end, and we couldn't update or track their acceptance over time.

We had an existing on-boarding flow that we could tap into to require new prompts and acceptances.


  • Users are not given the option to decline
  • Configuration will be managed by an internal team so we don't need to worry about users creating too many types of agreements.
  • Won't need to build out custom admin functionality or new onboarding screens


  • The system should be agnostic about the "type" of agreement.
  • Move existing hard-coded terms of service into the new functionality.




            describe('Service agreement getter', () => {
              it('should not return accepted agreements', () => {});
              it('should not return unaccepted historical agreements', () => {});
              it('should not return agreements from another team', () => {});
              it('should not return agreements for a type their team does not use', () => {})


Modified the onboarding component to allow dynamically populated messsages from the API.

Updated the "accept" button to fire a POST request.