# Discount codes for Stripe, pls

**URL:** <https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130>\
**Category:** Memberships & subscriptions\
**Created:** [July 27, 2020, 1:49pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130 "2020-07-27T13:49:06Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [July 27, 2020, 1:49pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/1 "2020-07-27T13:49:06Z")

</div>

Hi there,

Ghost/Stripe checkout doesn’t currently support discount codes.

These would let folks have a month or two discounted, for free, so they could trial membership. This would lean to more signups.

This is also something that Substack supports, and is very handy.

---

<div class="post-metadata">

**Author:** ![John](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/john/32/29288_2.png) [@John](https://forum.ghost.org/u/John)\
**Post date:** [July 27, 2020, 3:24pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/2 "2020-07-27T15:24:23Z")

</div>

Ghost does support free trials, documented here:

[https://ghost.org/docs/members/free-trial/](https://ghost.org/docs/members/free-trial/)

And you can already use/apply discount codes directly in Stripe, if you want to create special offers. It’s manual, but it works fine - I have quite a few setup myself

---

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [July 27, 2020, 3:52pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/3 "2020-07-27T15:52:45Z")

</div>

_amazing!!!_ thanks @John

---

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [July 28, 2020, 9:16am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/4 "2020-07-28T09:16:07Z")

</div>

ps. being able to incorporate coupon codes (not free trials) into the checkout screen would be great.

---

<div class="post-metadata">

**Author:** ![John](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/john/32/29288_2.png) [@John](https://forum.ghost.org/u/John)\
**Post date:** [July 28, 2020, 10:56am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/5 "2020-07-28T10:56:50Z")

</div>

Stripe are currently beta testing that - I’ve seen it and works well. I imagine they’ll release it relatively soon 🙂

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [July 29, 2020, 4:03pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/6 "2020-07-29T16:03:06Z")

</div>

Hi John - I’m hoping to do this as well as I have a few thousand members on a different site I’d like to bring over and I have to offer them a discount. It’s a bit tedious to do it manually but if you had a solution for something broader, that would really be cool.

---

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [July 31, 2020, 9:38am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/7 "2020-07-31T09:38:25Z")

</div>

hey Rob, you could always open membership on a public link at a discount, but only tell your members about it and keep it open for, say, 28 days?

That way you can invite them over for the discounted price, and then just switch to the regular price.

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [July 31, 2020, 4:54pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/8 "2020-07-31T16:54:04Z")

</div>

Thanks @jsh4 - that was kind of what I was thinking. However… I’ve been playing around a bit with how coupons might work and am happy to do a PR but for the life of me I can’t see where the checkout session is created. I’m doing a full scale search within the project and I’m utterly stumped.

I then got to thinking “why don’t I just create my own checkout” using Stripe Elements. I was thinking that I could apply a coupon there (which I can) but there’s no way, that I can see, to add the `member_id` to subscription.

Finally - I see how the membership API is being used to create the session then redirect off to Stripe. I can intercept all of it and make my own thing easily - I just want to pass in a coupon ID through the session which the docs say is possible:

> **[Build a subscriptions integration](https://stripe.com/docs/billing/subscriptions/build-subscriptions)**
>
> Create and manage subscriptions to accept recurring payments.

It would seem a simple thing to add to the API call… Happy to PR this if I could just get a pointer to where the Stripe Session is created.

---

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [August 4, 2020, 9:58am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/9 "2020-08-04T09:58:07Z")

</div>

sorry, can’t help you here… One for @DavidDarnes perhaps?

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [August 5, 2020, 5:19pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/10 "2020-08-05T17:19:17Z")

</div>

OK I think I figured this out. @John weigh in and let me know if I’m crazy :).

I dove into the `members-api` package and noticed that a `metadata` key was being passed in and, as far as I can tell, it’s not being used for anything currently. It _seems_ like it’s there for theming reasons? Not sure - anyway I worked up a Vue/axios call to the API endpoint that looks like this:

```auto
const sessionRes = await axios.get("/members/api/session");

const payload ={
    plan: "Monthly",
    identity: sessionRes.data,
    successUrl: location.href,
    cancelUrl: location.href,
    metadata: {coupon: 'asdasdasd'}
}
try{
    const stripeCheckoutSession = await axios.post("/members/api/create-stripe-checkout-session/", payload);

    Stripe(stripeCheckoutSession.data.publicKey).redirectToCheckout({
        sessionId: stripeCheckoutSession.data.sessionId 
    });
}catch(err){
    //if we're here we have a bad coupon code
}

```

I made _two small tweaks_ to the `createCheckoutSession` method, which were to pull the payload into a variable and then check for the presence of a coupon passed in through the `metadata`:

```auto
const payload = {
    payment_method_types: ['card'],
    success_url: options.successUrl || this._checkoutSuccessUrl,
    cancel_url: options.cancelUrl || this._checkoutCancelUrl,
    customer: customer ? customer.id : undefined,
    customer_email: customerEmail,
    metadata,
    subscription_data: {
        trial_from_plan: true,
        items: [{
            plan: plan.id
        }]
    }
}
if(metadata && metadata.coupon) payload.subscription_data.coupon = metadata.coupon;
const session = await this._stripe.checkout.sessions.create(payload);

```

As you can see, it works great when there’s a valid coupon code :).

![shot_361](https://us1.discourse-cdn.com/flex015/uploads/ghost2/original/2X/5/5c030f931c2d92ccc4c403b89f10f550e600a308.jpeg)

The one thing I’m not a super huge fan of is trapping the 400 here - ideally the API would return a wrapper for the checkout with a success/fail flag or the like and an error message the dev could do something with.

I’m happy to PR both things if you find this useful.

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [August 6, 2020, 7:50pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/12 "2020-08-06T19:50:49Z")

</div>

Hi friends me again - this is interesting… I got this to work by sidestepping the Ghost checkout process entirely, which is fun and interesting. I created a Firebase function (serverless) that accepts a plan name (“Monthly” or “Yearly”) along with a customer email. It pings Stripe to see if the customer exists and uses that customer information (which is another thing I wanted). It then sets up the checkout session, passing in the discount code if one was provided.

I didn’t expect it to work - but it did. The webhook coming from Stripe is reconciled by Ghost on the user’s email thankfully. The one thing that’s not present is the discount code on the user’s screen but… oh well. I suppose I can tweak that later with another serverless call.

If you’re interested in the code let me know - it’s pretty straightforward stuff.

---

<div class="post-metadata">

**Author:** ![signalnerve](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/signalnerve/32/9058_2.png) [@signalnerve](https://forum.ghost.org/u/signalnerve)\
**Post date:** [August 7, 2020, 4:00am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/13 "2020-08-07T04:00:41Z")

</div>

Stripe just announced coupon support for Checkout, shown in this tweet:

> <https://twitter.com/stripe/status/1291441519585406976?s=21>

Maybe this fixes this issue?

_edit:_ looks like it’s done with a `allow_promotion_codes` bool passed into the stripe checkout session call. i get that it might not be as clear cut as that (should it always default to true?) but looks like this is a good first step to this stuff landing. @robconery maybe if you’ve been looking at the source you know where this could fit in?

---

<div class="post-metadata">

**Author:** ![signalnerve](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/signalnerve/32/9058_2.png) [@signalnerve](https://forum.ghost.org/u/signalnerve)\
**Post date:** [August 7, 2020, 5:09am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/14 "2020-08-07T05:09:13Z")

</div>

ok well i made a PR for this :)

> <https://github.com/TryGhost/Members/pull/194>
>
> This PR adds support for Stripe's newly-added \[promo code feature in Stripe Chec…kout\](https://twitter.com/stripe/status/1291441519585406976). I've defaulted this value to \`true\` because it's fairly unobtrusive in the UI, and can safely be ignored if a new member subscribes and doesn't have a coupon to use.
> 
> The Stripe documentation on adding customer-facing promotion codes:
> https://stripe.com/docs/payments/checkout/set-up-a-subscription#coupons
> 
> I've tested this with a local installation and found that it adds the promo code UI as expected (see included screenshots with PR). I then completed the checkout process with a coupon and found that it successfully applied the coupon - woohoo!
> 
> \<details\>
> \<summary\>📷 Screenshots of the new coupon UI when redirected to Stripe Checkout\</summary\>
> \<img width="1200" alt="Screen Shot 2020-08-07 at 12 01 33 AM" src="https://user-images.githubusercontent.com/922353/89610839-390f4f80-d841-11ea-81a1-ae5d473d70fd.png"\>
> \<img width="1200" alt="Screen Shot 2020-08-07 at 12 01 44 AM" src="https://user-images.githubusercontent.com/922353/89610842-3ad91300-d841-11ea-976b-c8d7cf086814.png"\>
> \</details\>
> 
> \<details\>
> \<summary\>📷 Screenshots of the coupon being persisted into the invoice and Stripe customer after checking out\</summary\>
> \<img width="1144" alt="Screen Shot 2020-08-06 at 11 56 54 PM" src="https://user-images.githubusercontent.com/922353/89610964-812e7200-d841-11ea-9db2-3bf7e0656b7d.png"\>
> \<img width="1125" alt="Screen Shot 2020-08-06 at 11 56 37 PM" src="https://user-images.githubusercontent.com/922353/89610959-8095db80-d841-11ea-9aa5-b47bf61cec57.png"\>
> \</details\>
> 
> One thing worth noting: it doesn't appear that the coupon information shows up in the Members section in Ghost admin, just the pricing (e.g. $50/yearly, but no mention if I use a 100% coupon). Not sure how to solve that one, but being able to view the subscription in Stripe from the link on the member page seems like an acceptable compromise!
> 
> BTW, this is the first PR I've submitted to the extended Ghost universe of source code so happy to accept any changes or if there's a different way this should be done that feels better long-term, you're totally OK to close this :) just wanted to explore if I could get it working, and the resulting change was surprisingly straightforward!

---

<div class="post-metadata">

**Author:** ![John](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/john/32/29288_2.png) [@John](https://forum.ghost.org/u/John)\
**Post date:** [August 7, 2020, 7:39am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/15 "2020-08-07T07:39:38Z")

</div>

Yep, I mentioned above [10 days](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/5) ago that this was in progress and coming shortly — we’ve been beta testing it for several months.

The implementation suggested by @signalnerve is correct, and the question on the PR is the right one: Does it make sense for this to be on by default for everyone? At the moment: probably not.

We would consider adding it behind a config flag, to start.

---

<div class="post-metadata">

**Author:** ![jsh4](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jsh4/32/9756_2.png) [@jsh4](https://forum.ghost.org/u/jsh4)\
**Post date:** [August 7, 2020, 8:37am UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/16 "2020-08-07T08:37:01Z")

</div>

thanks for flagging, this is cool!

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [August 7, 2020, 3:50pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/17 "2020-08-07T15:50:53Z")

</div>

> [@signalnerve](#):
>
> allow\_promotion\_codes

Yep - adding this to the session code triggered the coupon at Stripe. Works great! I’m able to create the session using my serverless function so all’s well.

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [August 7, 2020, 6:18pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/18 "2020-08-07T18:18:21Z")

</div>

> [@John](#):
>
> the question on the PR is the right one: Does it make sense for this to be on by default for everyone? At the moment: probably not.

I think most people are content just sending people off to Stripe to setup a quick paywall to get off the ground. If they’re successful, however, not having promos/discounts is a bit of a blocker. Discount codes are extremely common in online checkouts and people ask for them constantly. This is going to be even more the case as people turn to online resources rather than in-person.

I would urge you to consider adding a checkbox to the labs page next to the Stripe signup.

---

<div class="post-metadata">

**Author:** ![robconery](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/robconery/32/8957_2.png) [@robconery](https://forum.ghost.org/u/robconery)\
**Post date:** [August 7, 2020, 6:41pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/19 "2020-08-07T18:41:51Z")

</div>

Oh - if anyone is curious about the Stripe solution that I got working I made a gist here. If you’re not familiar with Firebase this might look weird but you should be able to use the same code with Cloudflare workers or AWS Lambda.

So far it’s working well in testing so… fingers crossed.

> <https://gist.github.com/robconery/dd24077aa60209bf752c1802ea7614c4>

---

<div class="post-metadata">

**Author:** ![John](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/john/32/29288_2.png) [@John](https://forum.ghost.org/u/John)\
**Post date:** [August 7, 2020, 6:55pm UTC](https://forum.ghost.org/t/discount-codes-for-stripe-pls/16130/20 "2020-08-07T18:55:44Z")

</div>


