For discussing the development and integration of subscription-enabled shops using Shopify's Subscription APIs.
Building a new app. I've got a button that does the following:
1) Creates a new product
2) Creates a variant on new product
3) Creates a new selling plan group.
4) Assigns the subscription selling plan group to the variant.
All of these things seem to happen successfully. In the Dawn theme, I've added a variant selector. When I pick the variant with the recurring subscription plan assigned to it and checkout, there is no indication that the subscription has successfully started. As far as I can tell, its a one-time purchase.
My question is this:
1) how can I tell if the subscription has been successfully started (aside from waiting 24hrs to see if its renewed)?
2) Beyond simply submitting the variant with the subscription assigned to it, is there more I need to submit to checkout to initiate a successful subscription?
export async function action({ request }) { const { admin } = await authenticate.admin(request); const productResponse = await admin.graphql(`mutation { productCreate(input: { title: "Sweet new productzzY", productType: "TEST Product", vendor: "JadedPixel", options: ["Interval"] }) { product { id options { id name } } } }`, ); // Convert the response into JSON const productData = await productResponse.json(); const productId = productData.data.productCreate.product.id; const variantResponse = await admin.graphql(` mutation { productVariantCreate(input: { productId: "`+productId+`", price: "39.99", options: ["1 Week"], sku: "UNIQUE-SKU", title: "New Variant Title" }) { productVariant { id } userErrors { field message } } } `); const variantData = await variantResponse.json(); const variantId = variantData.data.productVariantCreate.productVariant.id; const planResponse = await admin.graphql(` mutation { sellingPlanGroupCreate(input: { name: "Subscribe and save", merchantCode: "subscribe-and-save", options: ["Delivery every"], position: 1, sellingPlansToCreate: [ { name: "Delivered every week", options: "1 Day", position: 1, category: SUBSCRIPTION, billingPolicy: { recurring: { interval: DAY, intervalCount: 1, anchors: { type: WEEKDAY, day: 1 } } }, deliveryPolicy: { recurring: { interval: DAY, intervalCount: 1, anchors: { type: WEEKDAY, day: 1 }, preAnchorBehavior: ASAP, cutoff: 0, intent: FULFILLMENT_BEGIN } }, pricingPolicies: [ { fixed: { adjustmentType: PERCENTAGE, adjustmentValue: { percentage: 15.0 } } } ] } ] }) { sellingPlanGroup { id } userErrors { field message } } } `); const planData = await planResponse.json(); const planId = planData.data.sellingPlanGroupCreate.sellingPlanGroup.id; // Logging the JSON to see the structure const planAssocResponse = await admin.graphql(` mutation { sellingPlanGroupAddProductVariants(id: "`+planId+`", productVariantIds: ["`+variantId+`"]) { userErrors { field message } } } `);
Solved! Go to the solution
This is an accepted solution.
Okay. Figured it out. I needed to add a checkout-system besides 'bogus payment processor' to get the store to make the store eligible for subscription. Duh.
Hey @finedining1
You'll need to pass along the selling plan ID when the customer adds the variant to cart as a subscription. More info here.
Scott | Developer Advocate @ Shopify
Thanks - I've got the form setup to pass along the selling Plan ID but I can't seem to access it from the frontend. While the selling plans appear in the product screen on the admin side (see below), they don't appear in the product object. I think there is an issue with how I am assigning the variants to the selling plan group.
Hey @finedining1
I don't believe that information is available via the AJAX API. Try using this example code in your theme.
Let me know if you get stuck.
Scott | Developer Advocate @ Shopify
To be clear, I got that console.log of the product object by adding this to the product page:
<script>
document.addEventListener('DOMContentLoaded', function() {
console.log("product: ", {{ product | json }});
});
</script>
As for the demo code, I've tried several different ways over the last few days with no luck. I've been adding itt to the default dawn theme product page like so:
<div class="product__info-wrapper grid__item{% if settings.page_width > 1400 and section.settings.media_size == "small" %} product__info-wrapper--extra-padding{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}">
<product-info
id="ProductInfo-{{ section.id }}"
data-section="{{ section.id }}"
data-url="{{ product.url }}"
class="product__info-container{% if section.settings.enable_sticky_info %} product__column-sticky{% endif %}"
>
{%- assign product_form_id = 'product-form-' | append: section.id -%}
{%- for block in section.blocks -%}
{%- case block.type -%}
{%- when '@app' -%}
{% render block %}
{%- when 'text' -%}
<p
class="product__text inline-richtext{% if block.settings.text_style == 'uppercase' %} caption-with-letter-spacing{% elsif block.settings.text_style == 'subtitle' %} subtitle{% endif %}"
{{ block.shopify_attributes }}
>
{{- block.settings.text -}}
</p>
{%- when 'title' -%}
<div class="product__title" {{ block.shopify_attributes }}>
<h1>{{ product.title | escape }}</h1>
<a href="{{ product.url }}" class="product__title">
<h2 class="h1">
{{ product.title | escape }}
</h2>
</a>
</div>
{%- when 'price' -%}
<div class="no-js-hidden" id="price-{{ section.id }}" role="status" {{ block.shopify_attributes }}>
{%- render 'price',
product: product,
use_variant: true,
show_badges: true,
price_class: 'price--large'
-%}
</div>
{%- if product.quantity_price_breaks_configured? -%}
<div class="volume-pricing-note" id="Volume-Note-{{ section.id }}">
<span>{{ 'products.product.volume_pricing.note' | t }}</span>
</div>
{%- endif -%}
<div class="product__tax caption rte">
{%- if cart.taxes_included -%}
{{ 'products.product.include_taxes' | t }}
{%- endif -%}
{%- if shop.shipping_policy.body != blank -%}
{{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }}
{%- endif -%}
</div>
<div {{ block.shopify_attributes }}>
{%- assign product_form_installment_id = 'product-form-installment-' | append: section.id -%}
{%- form 'product', product, id: product_form_installment_id, class: 'installment caption-large' -%}
<input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
{{ form | payment_terms }}
{%- liquid
assign current_variant = product.selected_or_first_available_variant | default: product.variants.first
assign current_selling_plan_allocation = current_variant.selected_selling_plan_allocation
if current_selling_plan_allocation == nil and current_variant.requires_selling_plan
assign current_selling_plan_allocation = current_variant.selling_plan_allocations | first
endif
assign offer = current_selling_plan_allocation | default: current_variant
-%}
{{ product.title }}
{{ offer.price | money }}
{% if offer.compare_at_price > offer.price %}
<s>{{ offer.compare_at_price | money }}</s>
<span>{% if offer.selling_plan %}Purchase options{% else %}Sale{% endif %}</span>
{% endif %}
{% form 'product', product %}
<input type="hidden" name="id" value="{{ current_variant.id }}">
<input type="hidden" name="selling_plan" value="{{ current_selling_plan_allocation.selling_plan.id | default: '' }}">
<fieldset>
<legend>Product options</legend>
{% for option in product.options_with_values %}
<label>{{ option.name }}</label>
<select>
{% for value in option.values %}
<option>{{ value }}</option>
{% endfor %}
</select>
{% endfor %}
</fieldset>
<!-- Pass the product object as JSON so it can be used to update selling plan information using JavaScript -->
<fieldset class="selling-plan-fieldset" data-product={{ product | json }}>
<legend>Purchase options</legend>
{% unless product.requires_selling_plan %}
<input type="radio" name="purchase_option"> One-time purchase
{% endunless %}
{% for group in product.selling_plan_groups %}
<input type="radio" name="purchase_option"> {{ group.name}}
{% for option in group.options %}
<label>{{ option.name }}</label>
<select data-position="{{ option.position }}">
{% for value in option.values %}
<option>{{ value }}</option>
{% endfor %}
</select>
{% endfor %}
{% endfor %}
</fieldset>
{% endform %}
{%- endform -%}
</div>
Okay its been a week stuck on this issue. I've completely refactored my app. I've gone through the subscription documentation, refactored my code, checked for correct scopes and the problem persists. I can successfully create subscriptions on the merchant side but they are not accessible on the storefront. I'm using the example code provided in the documentation on a vanilla dawn theme. No errors in the selling plan creation or association with the productid. Everything works except for the storefront. I've printed the product object into the console and there is no trace of selling plan information. Really not sure what is left to check at this point. Any ideas would be super appreciated.
This is an accepted solution.
Okay. Figured it out. I needed to add a checkout-system besides 'bogus payment processor' to get the store to make the store eligible for subscription. Duh.