This is a web app for managing the SFA membership program. It is both the frontend application that members can sign into as well as the API endpoints for multiple utilities.
The members data lives in a Digital Ocean PostgreSQL database.
Resources:
- A new member signs up. This is done using Stripe and will call
membership.streetsforall.org/api/stipe_members - We check the member payment and assign them a tier (1, 2, 3). We log the user to our database (table:
membersandmember_updates) - We place an API call to Printful to order merch depending on the tier of the user. We log the order in our database (table:
merch_orders) - We update the user in our [Mailchimp]((https://github.com/mailchimp/mailchimp-marketing-node/) Audience
- We generate an email verification and post it to our database (table:
email_verification_tokens) - We fire an email to the user with their login link and welcoming them to the program.
(There are other variables specified in .env.example that are required, but this covers the more complicated ones.)
Set up a local Postgres database to hold store memberships, merch orders, email attempts, discount codes, and more. An easy way is to use Docker. Then fill out the DO_ environment variables.
An email server is required to send welcome and login emails. You can use your Gmail account by creating an app password and setting the EMAIL_ environment variables.
A Zapier webhook is used for triggering notifications. For development purposes, you can create a dummy webhook using webhook.site. Update the MEMBER_ZAP environment variable with the webhook URL.
-
Create a sandbox.
-
Install the Stripe CLI.
-
Connect your CLI to Stripe by logging in:
stripe login
This should provide you with the necessary
STRIPE_SECRET_KEY. -
Open the Developer Workbench in the Stripe sandbox, then go to Webhooks.
-
Create two webhooks:
Name URL Events subscriptions https://test.members.streetsforall.org/api/subscriptions customer.subscription.created,customer.subscription.deleted,customer.subscription.updatedsessions https://test.members.streetsforall.org/api/sessions checkout.sessions.completed
Note
The test subdomain isn't actually real. But we use it in the sandbox to make sure no webhook calls affect our production instance. (They will be redirected in a subsequent step.)
-
For the subscriptions and sessions webhooks, get the Signing secret from the Developer Workbench and update the
STRIPE_SUBSCRIPTIONS_HOOK_SECRETandSTRIPE_SESSIONS_HOOK_SECRETenvironment variables, respectively. -
Start the listener to redirect webooks requests to your local machine:
stripe listen --load-from-webhooks-api --forward-to localhost:3000
This will route requests in the sandbox to the
/api/subscriptionsand/api/sessionsendpoints to your local machine. And your local machine will appear as a new destination in developer workbench.
Important
You will need to keep this running to forward the requests, so it's best to do so in a separate terminal window.
Install dependencies:
npm InstallThen start the local development server:
npm run devYou can perform test transactions in the Stripe sandbox UI, which should call the webhook in the local destination.
Tip
Stripe provides dummy credit card numbers you can use to create test transactions in the sandbox.
Alternatively, you can trigger specific webhook events directly by running the following (in a different terminal window).:
stripe trigger <event>This will send the event to the sandbox, which should then forward it back to your local machine if you've set everything up correctly.
Caution
We currently do not have non-production environments for Printful or Mailchimp. So be sure to immediately cancel any orders that are created in Printful, and archive any contacts that are created in Mailchimp.
In order to track metrics about subscriptions, analytics are collected when a new member signs up. To faciliate this, there is a custom /confirmation page that Stripe redirects the user to after the checkout process is complete.
Tip
This is configured on the Stripe side in the dashboard, under Payments, on the Payment Links page. The confirmation page is set by editing a link and going to the After payment tab. Refer to the Stripe documentation for more information.
The analytics are only registered if the checkout session is validated. This is done by a calling the Stripe API to retreive the session information. To cover all our bases currently, both a page view and an event trigger is registered in both Meta and Umami. (This may change as we refine the process in the future.) Since Umami is also used at the app level to track general page visits, there are two different root layout.tsx files:
- Under
(confirmation)/: This is only used for the confirmation page Stripe redirects to after checkout is complete. - Under
(main)/: This is used for all other pages.
(These parentheses-wrapped folders are Next.js route groups.)
The only difference between these two is that (confirmation)/layout.tsx initializes Umami without automatically registering all page views. This allows them to be registered programatically (only when the checkout session has been validated). (This isn't necessary for the Meta Pixel, because it isn't used in the rest of the app.)
Meta doesn't automatically register UTM parameters with page views, so they are only available in events. Meta's real-time information is meant more for testing purposes, but processed metrics are available almost instantaneously.
Navigate to the Events Manager and select the appropriate dataset. Go to the Test events tab.
Navigate to the Events Manager and select the appropriate dataset. The table at the bottom of the Overview tab should display both PageView and Subscribe events.
Umami doesn't display detailed properties about page views or events in real-time. However, processed metrics with this information are available almost instantaneously.
Navigate to Traffic → Realtime.
- Page views: Navigate to Growth → UTM.
- Events: Navigate to Traffic → Events. Select the
new-subscriptionEvent and the apporiate Property option corresponding the UTM tag you're interested in.
- does the members table receive update?
- does the member_updates table receive changes?
- does the merch_orders table receive changes?
- can users still login?
- does Printful build orders?
- does mailchimp update user?