Promotions
7 minute read
What you’ll learn
- What is a Connected Marketplacer integration
- What are promotions
- How promotions work in a Connected environment
- GraphQL examples used to manipulate promotions
Connected Integrations
Before discussing the use of Promotions, it’s worthwhile learning about the different types of Marketplacer configuration (both current and deprecated), as these configurations impact how promotions work.
We will only be focused on “Connected Integrations” in this article, discussion on the other 2 types of pattern are provided for (historical) context only.
The different Marketplacer configuration types are outlined below:
Configuration Type | Description | Cart & Checkout | Status |
---|---|---|---|
Full Stack | Instances of Marketplacer that use a Marketplacer developed frontend and made use of Marketplacer cart and checkout functionality. | Marketplacer | Deprecated |
Headless | Instances of Marketplacer that use an Operator-developed frontend and made use of Marketplacer cart and checkout functionality via API. | Marketplacer | Deprecated |
Connected | Instances of Marketplacer that use an Operator-developed frontend as well as cart and checkout functionality. | Operator supplied | Active |
What are promotions?
Promotions can be created by either the Operator or Seller to enable the application of discounts on a customer order, however they work slightly differently depending on the Marketplacer configuration type:
Configuration Type | How Promotions are applied |
---|---|
Full Stack | Applied automatically to the Marketplacer cart. Other than the existence of a valid, active promotion, no further action is required for promotions to be applied. |
Headless | Applied automatically to the Marketplacer cart. Other than the existence of a valid, active promotion, no further action is required for promotions to be applied. |
Connected | Promotions need to be explicitly applied to the order. The existence of a valid, active promotion does not mean it will be auto-applied to the order. |
What about coupons?
To round out our conversation on the different types of Marketplacer configuration, and more specifically the types of discount that can be applied, it’s worth mentioning Coupons. Coupons, like Promotions, also provide the ability to apply discounts to an order but in a discretionary way. This is probably best expressed in the following table:
Configuration Type | Promotions | Coupons |
---|---|---|
Full Stack | Auto applied to cart | Explicitly applied to cart |
Headless | Auto applied to cart | Explicitly applied to cart |
Connected | Explicitly applied to order | Not available Promotions could be used to drive coupon-like behavior |
The takeaway point here is that in a Connected configuration, the use of Promotions is at the discretion of the Marketplace Operator, and can be used to drive both auto applied and discretionary (coupon-like) discount behaviors.
How to use promotions in a Connected Environment
The following high-level journey describes how you would employ Promotions in a Connected configuration.
In the remainder of this article we will follow the above journey and illustrate the Marketplacer specific touch points, noting that we will only be covering the API and not the UI.
1. Creating a promotion
To create a promotion via the API you can use the promotionUpsert
mutation, this can be used by both Operators and Sellers:
mutation CreateAPromotion{
promotionUpsert(
input: {
attributes: {
name: "10% Off"
description: "10% off the listed price"
discountAmount: 10
discountType: PERCENT
# You can obtain Brand Ids via the "brands" query
brandsExcludedIds: ["QnJhbmQtNA==", "QnJhbmQtMTk="]
# You can obtain Taxon Ids via the "taxons" or "prototypes" queries
categoriesIncludedIds: ["VGF4b24tNzg="]
}
}
) {
errors {
field
messages
}
promotion {
id
name
}
}
}
In the above example we have not included every possible configuration, refer to the
promotionInput
type for more information.
2. Ingest promotions
Having created promotions in Marketplacer, you would then need to ingest them into your domain, you can use the promotions
query to do this:
query ReturnPromotions {
promotions(status: "active") {
nodes {
id
seller {
id
businessName
}
name
teaser
description
startDate
endDate
minimumSpend
maximumSpend
suspended
discountType
discountAmount
freeShipping
costPercentageBorneByMarketplace
loyaltyProgramLevels {
nodes {
name
}
}
freeShippingDomesticOnly
brandsIncluded {
edges {
node {
name
}
}
}
brandsExcluded {
edges {
node {
name
}
}
}
categoriesIncluded {
edges {
node {
displayName
}
}
}
categoriesExcluded {
edges {
node {
displayName
}
}
}
advertsIncluded {
edges {
node {
description
}
}
}
advertsExcluded {
edges {
node {
description
}
}
}
variantsIncluded {
edges {
node {
sku
}
}
}
variantsExcluded {
edges {
node {
sku
}
}
}
saleItemsExcluded
}
}
}
3. Render Promotions
This step would occur entirely in the Operator domain, outside of Marketplacer, it has been included for guidance purposes only.
You can use the data for promotions obtained in Step 2 to:
- Display as site wide promotions on your products
- Act as “coupons” that can be applied at your discretion
4. Apply Promotions at checkout
This step would occur entirely in the Operator domain, outside of Marketplacer, it has been included for guidance purposes only.
You would need to ensure that any relevant promotions that have been applied / selected are applied at your checkout step.
5. Place order in Marketplacer
A full overview of how you can create orders is covered in this article, (including the application of promotions).
Note: promotions are applied to order line items.
To apply a promotion to an order you need to:
- Provide the pre-discount value for the line item (in cents)
- Obtain the promotion id that you would like to apply
- Apply the (negative) promotion amount in cents to the line item
- Supply the amount (in cents) that you want to withhold from seller remittances
- Provide a description for the promotion (this will appear on customer invoices)
An example mutation is shown below.
mutation {
orderCreate(
input: {
order: {
firstName: "David"
surname: "Tennant"
phone: "972544939658"
emailAddress: "drwho@email.com"
address: {
address: "1 Church Street"
city: "Melbourne"
country: { code: "AU" }
postcode: "3000"
state: { name: "Victoria" }
}
}
lineItems: [
{
variantId: "VmFyaWFudC0xMDA0Nzk="
quantity: 1
cost: { amount: 27000 }
postage: { amount: 0 }
adjustments: [
{
adjustmentType: PROMOTION
amountCents: -2700
amountToWithholdFromSellerRemittanceCents: 0
description: "10% off promotion"
sourceId: "UHJvbW90aW9uLTI1"
}
]
}
]
}
) {
order {
id
legacyId
totalCents
companyName
invoices {
nodes {
id
legacyId
lineItems {
id
}
}
}
}
errors {
field
messages
}
}
}
Other points related to the application of promotions:
- You need to calculate / supply the promotion discount to apply (
amountCents
for the promotion) - You can apply multiple, separate promotions to the same line item, an example of this is shown below for the
lineItem
definition fororderCreate
(for brevity we have omitted the rest of the mutation call):
lineItems: [
{
variantId: "VmFyaWFudC0xMDAyMDY="
quantity: 1
cost: { amount: 20000 }
postage: { amount: 0 }
adjustments: [
{
adjustmentType: PROMOTION
amountCents: -2000
amountToWithholdFromSellerRemittanceCents: 0
description: "10% off promotion"
sourceId: "UHJvbW90aW9uLTE3OQ=="
}
{
adjustmentType: PROMOTION
amountCents: -1000
amountToWithholdFromSellerRemittanceCents: 0
description: "5% off coupon"
sourceId: "UHJvbW90aW9uLTE4MA=="
}
]
}
]
Adjustments
Promotions are 1 type of adjustment that you can apply to an order. The other type of adjustment is a custom fee, (e.g. additional fee for delivering to an inaccessible area). Unlike promotions, custom fees are applied at the Invoice level (not the line item). You can read more about adjustments here.6. Seller fulfills order
This step covers regular order fulfillment on the part of the Seller. If using the Seller API, the seller can understand the adjustments applied to line items by querying an invoice in the following way:
query GetMyOrders {
node(id: "SW52b2ljZS0xMzU2Ng==") {
... on Invoice {
legacyId
id
discountCents
subtotalCents
totalCents
commissionAmountCents
statusFlags
adjustments {
...adjuistmentFrgament
}
lineItems {
id
legacyId
quantity
status
adjustments {
...adjuistmentFrgament
}
}
}
}
}
fragment adjuistmentFrgament on Adjustment {
id
amountCents
adjustmentType
appliesTo
description
amountToWithholdFromSellerRemittanceCents
}
This would result in a response similar to the following:
{
"data": {
"node": {
"legacyId": 13566,
"id": "SW52b2ljZS0xMzU2Ng==",
"discountCents": -3000,
"subtotalCents": 20000,
"totalCents": 17000,
"commissionAmountCents": 1000,
"statusFlags": [
"PAID"
],
"adjustments": [], 👈 Custom Fees would appear here
"lineItems": [
{
"id": "TGluZUl0ZW0tMzk1Ng==",
"legacyId": 3956,
"quantity": 1,
"status": "ALLOCATED",
"adjustments": [ 👈 Promotions appear here
{
"id": "QWRqdXN0bWVudC00Mzky",
"amountCents": -2000,
"adjustmentType": "PROMOTION",
"appliesTo": "SUBTOTAL_DISCOUNT",
"description": "10% off promotion",
"amountToWithholdFromSellerRemittanceCents": 0
},
{
"id": "QWRqdXN0bWVudC00Mzkz",
"amountCents": -1000,
"adjustmentType": "PROMOTION",
"appliesTo": "SUBTOTAL_DISCOUNT",
"description": "5% off coupon",
"amountToWithholdFromSellerRemittanceCents": 0
}
]
}
]
}
}
}