Open andrewpaliga opened 8 years ago
@andrewpaliga,
The current Working Group charter [1] puts loyalty and coupons out of scope:
"Recommendations for loyalty schemes and coupons, digital receipts, digital credentials, tickets, and location services are out of scope."
There are nascent discussions in the Interest Group [2] about the idea of a future version of user experience including application of loyalty and coupons. I am behind schedule but actioned to propose a plan and I'd welcome your help in that forum.
There are also more general discussions going on around verifiable claims (and there's a joint task force between the Credentials Community Group and the Web Payments Interest Group on that topic).
Ian
@ianbjacobs thank you for the clarification. The slight confusion from my end was that the scope was listed under "Digital Wallets" while the interface for coupons could reside on the user agent, unless I'm missing something. We'd be happy to help define a process for applying gift card and discount codes.
@andrewpaliga we are looking at coupons and loyalty cards in the context of ecommerce in the Web Payments Interest Group and also as a adjunct to "verifiable claims". C'mon in!
@andrewpaliga,
The slight confusion from my end was that the scope was listed under "Digital Wallets" while the interface for coupons could reside on the user agent, unless I'm missing something.
I agree that the UI could be on the client side, and coupons/loyalty feel like a reasonable extension to the payment request experience we are working on today.
I'd be happy to chat with you about this; I have chatted with @jnormore as well.
Ian
What is the strategy for accepting gift card and discount codes in the payments api? Will this be the responsibility of the user agent or the payment app?
It seems to me that this would be easily supported by leveraging the user agent's data collection functionality as with shipping address etc.
This is further evidence that this functionality needs to be extensible.
Should we allow websites to request data that the user agent doesn't necessarily understand? Should we update my proposal on PR #65 to give the website more control over what is being requested?
WebIDL
enum DataType {
"date",
"number",
"address",
"email",
"telephone",
"url"
"string",
...
};
dictionary DataDescriptor {
required DOMString label;
required DataType type;
required boolean optional = false;
};
dictionary ShippingAddressDataDescriptor : DataDescriptor {
sequence<ShippingOption> shippingOptions = false;
};
dictionary PaymentOptions {
sequence<DataDescriptor> requestData;
...
};
Example website code:
{
requestData: [
{
label: "Shipping Address",
type: "address",
shippingOptions: [...]
},
{
label: "Email Address",
type: "email",
optional: true
},
{
label: "Voucher Code",
type: "string",
optional: true
}
]
}
Should we allow websites to request data that the user agent doesn't necessarily understand?
This type of flexibility would certainly help us implement the spec as a replacement to our current checkout.
Support for gift cards and discount codes is explicitly out of scope for this version of the API so I am going to mark this issue as postponed.
That said, there is a proposal here for a generic change to the API that would allow us to deal with this use case more explicitly down the line.
That proposal will need to be judged on it's own merit (as opposed to as a solution for this use case) and should be submitted as a PR for the group to discuss.
I'd recommend that data that doesn't get stored and is useful across many sites not be added to the spec. It's valuable to store shipping addresses. That data will be used on many sites and saves a lot of typing. Coupon codes are used once, so the browser won't store it for future use. At that point it's just a substitute for a form field.
It becomes a slippery slope as the payment sheet then becomes a substitute for HTML screens and will cause fragmentation (i.e., "should I implement this field in HTML or the payment sheet?").
Weirdly, I thought I had already put together a proposal for this, but can't find it on Github.
Here is another one.
Note: I wrote the following in such a way that we can just spin off a separate "Payment Request API: Coupons" spec. That way, this doesn't need to block on the main Payment Request API spec. It also makes it easier to shop around.
PaymentOptions
dictionarypartial dictionary PaymentOptions {
boolean requestCoupon;
}
requestCoupon
memberIndicates that the merchant allows a coupon to be applied during request for payment.
For example:
const options = {
requestShipping: true,
requestCoupon: true, // ✨
};
const request = new PaymentRequest(methods, details, options);
PaymentDetailsUpdate
dictionarypartial dictionary PaymentDetailsUpdate {
DOMString couponCode;
boolean couponAccepted;
CouponErrors couponErrors;
}
couponCode
memberServes as a placeholder coupon, which gets pre-populated in the payment sheet.
For example:
// fill it in, but don't apply it
request.show({ couponCode: "SPRING-SALE" });
// Show it, and apply it!
request.show({
couponCode: "SPRING-SALE",
couponAccepted: true,
});
couponAccepted
memberTells the browser to stop allowing the user to change the coupon code, and signal to the user that the code was accepted.
For example:
ev.updateWith({
couponCode: "SPRING-SALE",
couponAccepted: true,
});
couponErrors
memberAllows the merchant to signal errors related to the coupon code.
For example:
ev.updateWith({
couponErrors: { code: "Code already used." },
});
CouponErrors
dictionaryNote: follows model from https://github.com/w3c/payment-request/issues/647#issuecomment-385852164
dictionary CouponErrors {
DOMString code;
}
code
memberThe error corresponding to this particular code. See couponErrors
member for example.
PaymentRequest
interfacepartial interface PaymentRequest {
attribute EventHandler oncouponchange;
readonly attribute DOMString? couponCode;
}
oncouponchange
attributeFires when the user changes the coupon.
couponCode
attributeAllows merchants to access the updated coupon code during the request for payment.
PaymentResponse
interfacepartial interface PaymentResponse {
readonly attribute DOMString? couponCode;
}
couponCode
attributeAllows merchants to access the updated coupon code in the response.
async function doPaymentRequest() {
const options = { requestCoupon: true };
const request = new PaymentRequest(methods, details, options);
request.oncouponchange = ev => {
const promise = applySweetSweetSavings(request, details);
ev.updateWith(promise);
};
const response = await request.show();
//...
await response.complete("success");
// post it somewhere, including the `couponCode` applied
fetch("/invoices", {
method: "POST",
body: JSON.stringify(response.toJSON()),
});
}
async function applySweetSweetSavings({ couponCode }, { displayItems }) {
const couponErrors = await validateCouponCode(couponCode);
if (couponErrors) {
return { couponErrors };
}
// It's good, update total, add display item, whatever...
const { newTotal, additionalDisplayItem } = applySweetSavings(couponCode);
return {
couponErrors: undefined,
couponAccepted: true,
total: newTotal,
displayItems: [...displayItems, additionalDisplayItem].flatten(),
};
}
Thoughts?
Fixed couple of little things above, added more examples, links, etc.
Great place to start from! Nice work @marcoscaceres
Two minor concerns:
coupon
. I'm not sure it's universal terminology. Maybediscount code
would be better?couponAccepted
. The user should be allowed to change the code even if the merchant has accepted it.Can't wait to get some sweet sweet savings!
I think you have overloaded couponAccepted. The user should be allowed to change the code even if the merchant has accepted it.
I had the same thought. I don't think we would really need couponAccepted… if the merchant doesn't return an error from the event then we can assume it's valid. I also think we shouldn't restrict to a single applied coupon as that will still not be flexible enough for sites and we'd have to fix that later.
@adrianhopebailie wrote
- The word coupon. I'm not sure it's universal terminology. Maybe discount code would be better?
Agree that the name is not great and totally open to bikeshedding. The reason I didn't go with discountCode
was that it might not always be a "discount".
Few options, from Wikipedia's coupon entry: "coupon codes", "promotional codes", "promotion codes", "discount codes", "keycodes", "promo codes", "surplus codes", "portable codes", "shopping codes", "voucher codes", "reward codes", "discount vouchers", "referral codes" or "source codes".
My personal choice would be: promoCode
, as it's fairly generic, doesn't talk about discounts, and covers the "you get a free thing" use case... other option, offerCode
.
@adrianhopebailie, wrote:
- The user should be allowed to change the code even if the merchant has accepted it.
Ah, can you help me understand this a bit more? do you mean remove it? Like, this user story:
Or, this user story:
So, with the above, the payment sheet should have the following affordances:
@mnoorenberghe wrote:
I don't think we would really need couponAccepted… if the merchant doesn't return an error from the event then we can assume it's valid.
Agree! Will drop couponAccepted
.
I also think we shouldn't restrict to a single applied coupon as that will still not be flexible enough for sites and we'd have to fix that later.
Yes, I was thinking the same thing. My limited personal experience was that I'd only ever seen the ability to apply a single code. Folks who know better: @andrewpaliga, @michelle-stripe, @jenan-stripe, your feedback is critical here:
+1 to offerCode. I can also live with promoCode.
Do you have stores that accept more than one coupon code?
I'm pretty sure I've used multiple coupon codes on a site before. e.g. coupon code A is for buying N products by Brand 1, coupon code B is a discount offered solely by the merchant, not in partnership with a brand.
If yes, does the number of coupon codes allowed need to be limited by the merchant?
If so, that should be handled by the event + updateWith
rather than be passed on to the UAs to handle IMO.
Could someone remind me of the recent discussion that sparked re-opening this? I believe it was from a merchant test IIRC. Did the test allow for coupon code entry before the PaymentRequest dialog appears?
From what I gather, it might have been sparked because of a recent call where Andre (https://github.com/lyverovski) mentioned some experiments we've been running around Payment Request. See minutes here: https://www.w3.org/2018/05/03-wpwg-minutes
lyver: We've been running some experiments for several months with PR API running on a number of enterprise level clients ... we are putting together a brief that we will share with this group ... there are two points that I want to raise: merchants are not necessarily skittish; they have trusted us as a platform ... but what's missing for them is support for discount codes. Up to half of people have dropped out since they want to go through legacy UX to get the discount code. I think that is missing from the focus of the next six months ... the other thing is that buyers themselves are skittish...they see the payment sheet open and has little merchant branding, which may scare some off.
If this is truly what re-opened the discussion and what you were asking about; our experiment allowed the customer to click a "Discount or gift card?". That would bring them to our normal checkout rather then them being able to apply a coupon code and then proceeding with Payment Request.
As Andre mentioned, we'll be sharing the rest of the learnings and the experiment setup soon.
If so, that should be handled by the event + updateWith rather than be passed on to the UAs to handle IMO.
So, just error the last one? Could work, but it means the user might enter more codes than they need to. If we restrict it, to say: "3", then the browser just doesn't provide an option to add another.
Could someone remind me of the recent discussion that sparked re-opening this?
See priorities (and related "ACTION"): https://www.w3.org/2018/05/03-wpwg-minutes#item03
Taking feedback thus far...
This proposal enhances the Payment Request API, allowing an end user to enter one or more "offer codes" when making a purchase.
Offer codes, known also as coupon codes, promotional codes, discount codes, etc. are tokens issued by merchants that, when applied to a payment request by an end user, can affect a payment request by, for example, providing a discount.
Via the API, merchants can indicate if they support offer codes at all, and limit the number of offer codes the user can provide, as well as inform the end user of potential errors with the provided offer code(s).
The following are all out of scope, and are the responsibility of merchants:
An offer code is a string that represents an opaque token.
An offer code can only be apply once per payment request, allowing them to be uniquely identified.
For example, "SUMMER-SALE".
PaymentOptions
dictionarypartial dictionary PaymentOptions {
// 255 max, 0 means no offer codes accepted
octet requestOfferCodes = 0;
}
requestOfferCodes
memberIndicates that the merchant allows the user to apply N offer codes during request for payment.
Value of 0 means that the merchant does not accept any offer codes.
For example:
const options = {
requestShipping: true,
requestOfferCodes: 3, // Up to 3 ✨
};
const request = new PaymentRequest(methods, details, options);
PaymentDetailsUpdate
dictionarypartial dictionary PaymentDetailsUpdate {
sequence<DOMString> offerCodes;
sequence<OfferCodeError> offerCodeErrors;
}
offerCodes
memberA list of strings representing offer codes, which are presented to the user.
For example:
// Show it
request.show({
offerCodes: ["SPRING-SALE", "BONUS-DISCOUNT"],
displayItems: itemsIncludingDiscounts,
});
OfferCodeErrors
memberAllows the merchant to signal errors related to one or more offer codes.
In case of duplicates, last one wins.
For example:
ev.updateWith({
offerCodeErrors: [
{ offerCode: "SPRING-SALE", error: "Code already used." },
// Duplicate, oops
{ offerCode: "SUMMER-SALE", error: "This is ignored." },
{ offerCode: "SUMMER-SALE", error: "Invalid code! Try again." },
],
});
OfferCodeError
dictionarydictionary OfferCodeError {
required DOMString offerCode;
DOMString error;
}
offerCode
memberThe identifier of the offending offer code.
PaymentRequest
interfacepartial interface PaymentRequest {
attribute EventHandler onoffercodeschange;
readonly attribute FrozenArray<DOMString> offerCodes;
}
onoffercodeschange
attributeFires when the user adds, deletes, or updates an offer code.
offerCodes
attributeAllows merchants to access the updated offer codes during the request for payment.
PaymentResponse
interfacepartial interface PaymentResponse {
readonly attribute FrozenArray<DOMString> offerCodes;
}
offerCodes
attributeThe final list of offer codes that were applied to the payment request.
async function doPaymentRequest() {
const options = { requestOfferCodes: 5 };
const request = new PaymentRequest(methods, details, options);
request.onoffercodeschange = ev => {
const promise = applySweetSweetSavings(request, details);
ev.updateWith(promise);
};
const response = await request.show();
//...
await response.complete("success");
// post it somewhere, including the `offerCode` applied
fetch("/invoices", {
method: "POST",
body: JSON.stringify(response.toJSON()),
});
}
async function validateOfferCode(code) {
return fetch(`is-valid?code=${code}`).then(r => r.json());
}
async function applySweetSweetSavings({ offerCodes }, { displayItems }) {
const offerCodeErrors = await Promise.all(
offerCodes.map(validateOfferCode)
).then(arr => arr.flatten());
if (offerCodeErrors.length) {
return { offerCodeErrors };
}
// It's good, update total, add display item, whatever...
const { newTotal, additionalDisplayItem } = applySweetSavings(offerCode);
return {
OfferCodeError: undefined,
total: newTotal,
displayItems: [...displayItems, additionalDisplayItem].flatten(),
};
}
:wave: I can provide some guidance from the Shopify side here. Take all of this with a grain of salt as what is best for our platform might not apply for the broader public of Payment Request.
To start it off, Shopify uses the field for both discount codes and gift cards alike. Now the interesting part here is that we only ever allow the customer to apply one of each. I'll follow below with some user stories and scenarios that we found to work best for the user experience.
As a side note (and this might become more of a browser vendor implementation detail), we change the copy on the offer code
field per merchant use case. For example:
We found this to be the least confusing of experiences for the user. This might lead us to wonder if the copy should be customizable by the integrator. 🤷♂️
Finally, we allow discount codes to be applied through URL permalinks, to support email promotions for example.
As such, here are the features that could be interesting to have (user stories and scenarios to follow):
offer code
field to be surfacedoffer code
to applied by the integratoroffer code
to be removedNotice that the feature of editing a offer code
is not mentioned; for Shopify at least, we find that as long as a offer code
can be overriden (the last offer code applied - be it a discount or gift card - takes precendence as long as it's valid) and these can be removed, there would be no need to have the ability to edit one. Thus, we also never deactivate or change the state of the offer code
field; rather, offer code
line iterms surface as removable receipt line items on our checkout.
All of that being said, I love your latest proposition @marcoscaceres! I'd love to discuss a bit more the following things:
requestOfferCodes
attribute necessary? If we would consider Payment Request having a single offer code
input field that is either there or not, with no possibility to edit offer codes (only to override them), is that attribute still necessary? I quite liked the idea of keeping it just as a boolean (as per the first draft)offerCodes
being populated affect the UI? i.e. Does the integrator still have to add a display item themselves for an offer code line item?This is to say, should the offer code input concept be seperated from the offer code line item? Could it be possible to make offerCodes part of the displayItems rather than a seperate entity?
Thanks y'all on your comprehension for this very long post. Hopefully this provides more insight than noise on further offer code discussions.
As a merchant
I want to offer discount codes on my store
In order to drive sales to my shop
As a merchant
I want to offer gift cards on my store
In order to drive recurring sales to my shop
Scenario: A customer applies multiple reductions to their checkout
Given a merchant supports both discount codes and gift cards
And the merchant has a "PROMO10" discount code, which reduces the order by 10%
And the merchant has a "PROMO20" discount code, which reduces the order by 20%
And the merchant has a "THANKS" gift card code, which reduces the order by 10$
When I start the checkout process
And I have a single "Digital Game" item of value 20$
Then I see a field with copy "Discount code or Gift Cards"
When I enter the discount code "PROMO10"
Then I see my receipt line items as such:
| line item | value |
| Digital Game | 20$ |
| PROMO10 | -10% |
| Total | 18$ |
When I enter a discount code "PROMO20"
Then I see my receipt line items as such:
| line item | value |
| Digital Game | 20$ |
| PROMO10 | -20% |
| Total | 16$ |
When I enter a gift card code "THANKS"
Then I see my receipt line items as such:
| line item | value |
| Digital Game | 20$ |
| PROMO20 | -20% |
| THANKS | 10$ |
| Total | 6$ |
When I remove the discount code
Then I see my receipt line items as such:
| line item | value |
| Digital Game | 20$ |
| THANKS | 10$ |
| Total | 10$ |
@Krystosterone, this is invaluable feedback! Thank you!
To start it off, Shopify uses the field for both discount codes and gift cards alike. Now the interesting part here is that we only ever allow the customer to apply one of each. I'll follow below with some user stories and scenarios that we found to work best for the user experience.
I wonder if we need to treat each differently, because each can have a different input modality. For instance, I can scan iTunes gift cards with my camera.
(We don't need to get this fancy... just showing what user's expectations might be - at least, I'd want a comparable experience, because the iTunes OCR input is a real treat on many levels.)
As a side note (and this might become more of a browser vendor implementation detail), we change the copy on the offer code field per merchant use case. For example:
Then we could have:
requestOfferCodes: true,
requestGiftCards: false,
That would also allow the browser to localize the copy in the way you demonstrated.
Finally, we allow discount codes to be applied through URL permalinks, to support email promotions for example.
I don't know what this means exactly. That the code is a URL? That's ok, I think.
rather, offer code line items surface as removable receipt line items on our checkout.
Ah, so PaymentItem
have an associated offerCode
, and then we would need some kind of event for the removal (current proposed model might allow for this).
It might get tricky if you have multiple displayItems
items with the same code applied. I guess the browser groups them together by code, and then allows trashing them all at once... yeah, that might be nice.
Is the requestOfferCodes attribute necessary? If we would consider Payment Request having a single offer code input field that is either there or not, with no possibility to edit offer codes (only to override them), is that attribute still necessary? I quite liked the idea of keeping it just as a boolean (as per the first draft)
In the case where you can trash offer codes from the displayItem
, directly, then it could work.
How does offerCodes being populated affect the UI? i.e. Does the integrator still have to add a display item themselves for an offer code line item?
My thinking was that they would show up in the UI, but the user would need to apply the ones they want (if any).
This is to say, should the offer code input concept be seperated from the offer code line item? Could it be possible to make offerCodes part of the displayItems rather than a seperate entity?
Yeah, something like that could work. I'll need to rethink it all now :)
@marcoscaceres Bike-shedding yay! I propose: checkoutCode
😬
+1 to both stories. I agree we can just drop the couponAccepted flag. "Applying" the coupon is done by the merchant through the line items. i.e. If the merchant accepts a coupon they can:
couponErrors
I am a little skeptical that we really need to encompass every payment flow, like coupon codes, in the browser's built-in payment sheet. This seems like something that can easily be applied in the "shopping cart" phase, before clicking the "checkout" button. But I guess I'll leave questions of "should we" to the experts/working group, and instead help with the "how do we" questions...
partial dictionary PaymentOptions { // 255 max, 0 means no offer codes accepted octet requestOfferCodes = 0; }
Don't use octet in this way, or impose arbitrary computer-ese limits like 255 in scenarios where they aren't domain-appropriate. Note that in this design passing 257 will be the same as passing 1.
See https://w3ctag.github.io/design-principles/#numeric-types for the general guidance in this area.
ev.updateWith({ offerCodeErrors: [ { offerCode: "SPRING-SALE", error: "Code already used." }, // Duplicate, oops { offerCode: "SUMMER-SALE", error: "This is ignored." }, { offerCode: "SUMMER-SALE", error: "Invalid code! Try again." }, ], });
To avoid the duplicate problem, you could use record<DOMString, DOMString>
, so that the above becomes
ev.updateWith({
offerCodeErrors: {
"SPRING-SALE": "Code already used.",
"SUMMER-SALE": "Invalid code! Try again."
}
});
Maybe this is inconsistent with other error-providing plans though.
I'm also not sure if it makes a lot of sense that coupons can be applied in the browser payment sheet. What would happen if the customer uses a coupon / gift cards which will reduce the payable amount to zero. As @theball already said, I am also seeing the payment sheet more for data, which rarely changes from a customer perspective. Coupon codes, gift cards or other promotions are often handled separately in many shops which could also lead to implementation problems.
@domenic said:
I am a little skeptical that we really need to encompass every payment flow, like coupon codes, in the browser's built-in payment sheet. This seems like something that can easily be applied in the "shopping cart" phase, before clicking the "checkout" button.
It does seem to introduce a fair amount of complexity. If we supported offer codes only in the shopping cart phase, presumably we could show the amount applied in a "view order details" interface within the payment sheet (as a PaymentItem
with a negative amount)...
I think it's very valuable to ask ourselves if coupon codes should be in scope of Payment Request. Hopefully the discussions we have here might provide future heuristics on deciding if further iterations should benefit from certain features or not.
Coupon codes seem to be one of the last concepts that have impact on receipt line items and total price, but are still not part of the Payment Request. The argument of presenting the field before the sheet is valid, but we would argue that this is not be the best of user experiences. For example, using Baymard's E-Commerce Checkout Usability Benchmark and Report[1], they mention:
On sites that neglected to do neither, i.e. both displayed coupon and promotional form fields directly in the default form flow, and placed them above the primary purpose of the checkout step, severe issues were observed, with 30-60+% of subjects coming to a full stop and examining the promotions. For some it even caused site abandonments.
As such, they suggest:
We suggest that not having promo codes in the sheet puts the onus on the merchant to figure out what is the best way to allow for promo codes to be accepted on their store (through the cart, for example). Depending on the merchant offerings, this might become quite intricate to do correctly and could very well lead to customers never clicking on the "checkout" button in the first place.
These two best practices can very well be implemented by browser vendors and provide for the best user experience. At Shopify, we follow the same rationale, as our very own experimentation also echoed the same issues.
To provide context, Shopify allows merchants to have full control over their storefront, but not over the checkout (this last part is controlled by our platform). The reasoning being that, as a platform, we want to provide the best UI and UX for the purchase experience to the customer. This also meant that when implementing promo codes, we only implemented them on the checkout process, rather than on the cart. We could have very well implemented an API for merchants to present their own promo code field, but went against that approach for all of the reasons stated previously.
As for the complexity, I would argue that it might be valuable to first decide if this is a problem worth solving. We can then iterate on the optimal API possible and discuss complexity as we go.
As for the complexity, I would argue that it might be valuable to first decide if this is a problem worth solving.
Agree, and it's clear this is a larger/more complicated than we (ok, just me! 😓) had initially envisioned.
We can then iterate on the optimal API possible and discuss complexity as we go.
I'd like for us to finish the things in the CR-Exit list, then come back to this when we have more available resources to fully explore the problem and prototype solutions. Nevertheless, I'd encourage interested folks to continue the discussion.
I don't want to be THAT GUY but I think we're starting to feel the pain from ignoring the early calls within the WG to design a basic payment API and a separate "checkout API" that was a composition of payments and other data collection.
By incorporating the collection of non-payment data like shipping address, email address etc. into the API in the way we did we must now constantly evaluate new requests for data collection against an unclear set of criteria for inclusion.
I agree with @marcoscaceres that we should focus, right now, on the CR-Exit list of issues and perhaps consider a quite different shape for a v2 API that is more composable?
@marcoscaceres @adrianhopebailie Totally didn't want to take up your time, as CR-Exit issues are more pressing for sure!
Whenever it's appropriate, we can circle back to this. If I ever think of anything else, I'll just keep posting here but feel free to ignore me for the time being.
v2 API that is more composable
Would love to see where that would lead!
@adrianhopebailie mentioned and "unclear set of criteria for inclusion" of features like discount codes.
I get the sense from discussions that lots of users may be dropping out of the sheet since they can't enter a discount code. That motivates me to want to hear good proposals for inclusion because:
So while the criteria for inclusion may not be clear, this particular feature seems to be important to user acceptance of the sheet.
Ian
Agreed, especially if by "user" we mean "merchant". ;-)
Agreed, especially if by "user" we mean "merchant".
Actually I think we mean "shoppers". i.e. Shoppers are confronted with a checkout sheet and have no way to enter a discount code so they drop out. This is obviously bad and, I agree, sufficient motivation to figure this out.
There are two issues here:
Let's constrain this thread to 1 and anyone with thoughts on 2 can make some proposals that we might consider as a WG for a v2 (@Krystosterone - tell us what your ideal API would look like, knowing now what we do about how this all fits together)
@adrianhopebailie Actually I think we mean merchants, because when @lyverovski gave us a report on their deployment experiment recently the feedback was "merchants are dropping out because they can't show discount codes to shoppers". If merchants can't deploy discount codes, shoppers can't use them, so perhaps we're splitting hairs. :-)
Hi all, we discussed at the WPWG teleconference today: https://www.w3.org/2018/05/31-wpwg-minutes#item01
The sentiment on the call was:
Ian
An important part of Shopify's checkout is the ability for the user to enter a discount code and or gift card at any point during the checkout (shown below). Once the discount or gift card code is verified the checkout balance is adjusted accordingly.
Step 1 - shipping
Step 2 - delivery
Step 3 - payment
The majority of checkout on the web support gift and promotional codes as well. Examples from Amazon and Nike below.
What is the strategy for accepting gift card and discount codes in the payments api? Will this be the responsibility of the user agent or the payment app?
There has been related discussion on the ability for the merchant to require the collection of certain shipping and billing information. This is similar but gift card and discount codes are more complex as they require an additional verification step to be carried out by the merchant. This verification could be accomplished through a callback to the merchant where they would be responsible for any updates.
Note: It’s more common to include gift card and discount entry in the payments step of checkout, however, we have experienced better cart conversation rates by making the option available throughout our checkout experience.