Shopify Plus Integration

CHANGE powers end-to-end donation processing. This guide will walk through how to integrate CHANGE into your Shopify Plus store.

For Shopify Plus, we recommend a serverless approach. In this guide, we’ll use AWS Lambda to submit a donation whenever a customer makes a purchase.

AWS Lambda

Nonprofit Lambda

Your shop may want to donate to different nonprofits based on product. This “product to nonprofit” mapping will be consumed at time of donation. To avoid repeating this mapping in several locations, we suggest keeping this logic in its own service.

Create a Lambda with the following implementation:

const NONPROFITS = {
'SKU_shoes': 42,
'SKU_jacket': 123
};

exports.handler = async (event) => {
const {skus} = event.queryStringParameters;
return {
statusCode: 200,
nonprofit_ids: skus.map(sku => NONPROFITS[sku])
}
};

For the rest of this guide, we’ll assume this Lambda is deployed and available at https://my.lambda/nonprofits.

Donation Lambda

const crypto = require('crypto');

// Your webhook secret, available after creating a Shopify webhook.
SHOPIFY_SECRET = 'shhh';
// Your CHANGE secret, available from your CHANGE dashboard.
CHANGE_SECRET = 'shhh';

exports.handler = async (event) => {
const {body, headers} = event;

// Verify that the request is from Shopify.
verified = verifySource(body, headers['X-Shopify-Hmac-SHA256']);
if (!verified) {
return { statusCode: 401 };
}

const order = JSON.parse(body);
const skus = order.line_items.map(item => item.sku);

// The nonprofit is determined by the Nonprofit Lambda.
const nonprofitIDs = await fetch(`https://my.lambda/nonprofits?skus=${skus}`);

// Submit the donation information to CHANGE.
submitDonations(order.id, nonprofitIDs);

// Shopify expects a 200 response.
return { statusCode: 200 };
};

async function submitDonations(orderID, nonprofitIDs) {
await fetch('api.getchange.io/donations/create', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
amount: 1,
nonprofit_ids: nonprofitIDs,
order_id: order.id
})
});
}

function verifySource(data, hmacHeader) {
const hash = crypto.createHmac('sha256', SHOPIFY_SECRET)
.update(data)
.digest('base64');
return crypto.timingSafeEqual(hash, hmacHeader);
}

Donation funds processing: Whether API calls to /donations/create move donation funds or not depends on your business arrangement with CHANGE.

For the rest of this guide, we’ll assume this Lambda is deployed and available at https://my.lambda/donation.

Shopify Webhook

Add a Webhook for Order creation.

Go to your Shopify store admin, then Settings > Notifications > Scroll to the bottom of the page and click “Create webhook”.

In the popup, select Event: Order creation, and enter the URL of your Donation Lambda, https://my.lambda/donation. Click “Save webhook”.

Adding a shopify webhook

Shopify will then provide you with a shared secret:

Shopify webhook secret

Copy the shared secret, and paste it in the Donation Lambda as the SHOPIFY_SECRET:

// Your webhook secret, available after creating a Shopify webhook.
SHOPIFY_SECRET = 'your-shopify-secret';

Your webhook is ready to go!

Nonprofit ID

The nonprofit_id depends on which product is being/has been purchased. We can look this up with the Donation Lambda service that we created in the previous section. Assuming the Lambda is available at https://my.lambda/nonprofits, the following script can be used to populate nonprofit_id:

<script>
const socialElement = document.querySelector('change-social-content');
fetch('https://my.lambda/nonprofits?sku=[{checkout.line_items | map: "sku"}]')
.then(JSON.parse)
.then(result => {
// If there are multiple line items, decide which one we should render
// social media content for.
socialElement.nonprofit_id = result[0];
});
</script>
Made with ❤ in San Francisco | Changelog | Status