Shopify handles a significant portion of ecommerce security automatically. The platform manages infrastructure security, SSL certificates, DDoS protection, and PCI DSS Level 1 compliance for payment processing. This is one of the strongest arguments for choosing a hosted platform over self-hosted solutions like WooCommerce or Magento.

But “Shopify handles security” is a dangerous oversimplification. Security is a shared responsibility. Shopify secures the platform; you are responsible for securing everything you build on top of it. Custom theme code, third-party apps, API integrations, staff permissions, and customer data handling all fall squarely within the merchant’s domain.

This guide covers the security practices that every Shopify store should implement, with particular focus on the areas where we see the most vulnerabilities across the stores we audit as part of our Shopify development work. These are not theoretical concerns — they are patterns we encounter regularly in production stores.

The shared responsibility model

Understanding what Shopify secures versus what you must secure yourself is the foundation of a sound security posture. Getting this wrong leads to either complacency (assuming Shopify handles everything) or wasted effort (trying to secure things that Shopify already manages).

What Shopify handles

  • Infrastructure security — server hardening, network security, data centre physical security, and redundancy.
  • SSL/TLS certificates — automatic provisioning and renewal for all stores and custom domains.
  • DDoS protection — traffic filtering and mitigation at the platform level.
  • PCI DSS Level 1 — the checkout and payment processing infrastructure meets the highest PCI standard.
  • Platform updates — security patches are applied automatically without merchant intervention.
  • Checkout security — the checkout flow is isolated and protected from custom code injection.

What you must handle

  • API key security — storing, rotating, and scoping API credentials properly.
  • Staff account security — two-factor authentication, permission management, and access reviews.
  • Theme code security — preventing XSS vulnerabilities, output encoding, and safe Liquid practices.
  • Third-party app vetting — assessing permissions, data access, and trustworthiness of installed apps.
  • Content Security Policy — controlling which external resources your storefront can load.
  • Customer data handling — GDPR compliance, data retention policies, and secure data transmission.
  • Custom integration security — securing webhook endpoints, middleware, and external system connections.

Security breaches on Shopify almost never originate from the platform itself. They come from weak passwords, leaked API keys, malicious apps, or vulnerabilities in custom code. Focus your security efforts where the actual risk lies.

Diagram showing the shared responsibility model for Shopify security
The shared responsibility model: Shopify secures the platform infrastructure, while merchants are responsible for securing their code, integrations, and access controls.

API key management

API keys are the single most common security vulnerability we find in Shopify stores. Developers commit keys to Git repositories, hardcode them into theme files, share them over email, and never rotate them. Any one of these practices can lead to a serious breach.

Types of Shopify API credentials

Shopify has several types of API credentials, each with different security implications:

  • Admin API access tokens — full read/write access to store data. Treat these like database passwords.
  • Storefront API tokens — public, read-only tokens designed for client-side use. Lower risk but should still be scoped correctly.
  • Private app credentials — legacy authentication method with API key and password pairs.
  • Custom app credentials — the current recommended approach using app-level API access tokens.

Secure storage patterns

# .env file (NEVER committed to version control)
SHOPIFY_ADMIN_API_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxx
SHOPIFY_STOREFRONT_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SHOPIFY_STORE_DOMAIN=your-store.myshopify.com
SHOPIFY_API_VERSION=2026-01

# .gitignore (must include)
.env
.env.*
!.env.example

For production deployments, use your hosting provider’s environment variable management:

# Vercel
vercel env add SHOPIFY_ADMIN_API_TOKEN production

# Railway
railway variables set SHOPIFY_ADMIN_API_TOKEN=shpat_xxxx

# Fly.io
fly secrets set SHOPIFY_ADMIN_API_TOKEN=shpat_xxxx

API scope minimisation

Every API credential should have the minimum scopes required for its function. If an integration only reads product data, it should not have write access to orders or customers. This principle of least privilege limits the blast radius if a credential is compromised.

// When creating a custom app, request only what you need
// BAD: requesting everything
const scopes = 'read_products,write_products,read_orders,write_orders,read_customers,write_customers';

// GOOD: requesting only what the integration needs
const scopes = 'read_products,read_inventory';

Key rotation schedule

API keys should be rotated on a regular schedule and immediately after any suspected compromise:

  • Admin API tokens — rotate every 90 days minimum.
  • After staff departures — rotate all credentials the departing staff member had access to.
  • After a security incident — rotate all credentials immediately.
  • After a third-party breach — rotate any credentials shared with or accessible to the affected party.
API key rotation schedule and secure storage workflow
A structured approach to API key management includes secure storage, scope minimisation, regular rotation, and immediate rotation after incidents.

Content Security Policy implementation

A Content Security Policy (CSP) is an HTTP header that tells the browser which external resources your page is allowed to load. It is one of the most effective defences against cross-site scripting (XSS) attacks and data injection attacks.

Without a CSP, any injected script can load resources from any domain — sending customer data to external servers, loading malicious code, or hijacking form submissions. With a properly configured CSP, the browser blocks these unauthorised resource loads before they execute.

Basic CSP for Shopify themes

Shopify’s Liquid templates allow you to set CSP headers via the content_for_header output and theme settings. For custom implementations, the CSP should be configured in the theme’s layout file or via a Shopify app that modifies HTTP headers:

<!-- In theme.liquid, add a meta CSP as a baseline -->
<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' 'unsafe-inline' https://cdn.shopify.com https://monorail-edge.shopifysvc.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.shopify.com;
  font-src 'self' https://fonts.gstatic.com https://cdn.shopify.com;
  img-src 'self' data: https://cdn.shopify.com https://*.shopifycdn.com;
  connect-src 'self' https://monorail-edge.shopifysvc.com https://*.shopifycloud.com;
  frame-ancestors 'none';
">

Adding third-party services

Each third-party service you use requires explicit CSP entries. This is where most CSP implementations become complex. Document every external domain your store loads resources from:

/* Example: CSP additions for common Shopify integrations */

/* Google Analytics / GTM */
script-src https://www.googletagmanager.com https://www.google-analytics.com;
img-src https://www.google-analytics.com;
connect-src https://www.google-analytics.com https://analytics.google.com;

/* Klaviyo */
script-src https://static.klaviyo.com https://a.klaviyo.com;
img-src https://static.klaviyo.com;
connect-src https://a.klaviyo.com;

/* Judge.me reviews */
script-src https://cache.judge.me;
style-src https://cache.judge.me;
img-src https://cdn.judge.me;

The key principle: start restrictive and add exceptions as needed. Never use * wildcards in your CSP unless absolutely unavoidable for a specific directive. Each wildcard entry undermines the entire policy’s effectiveness.

Testing your CSP

Use the browser’s developer console to identify CSP violations. Chrome reports blocked resources in the console with clear messages indicating which directive was violated and which domain was blocked:

// Console output for CSP violations
Refused to load the script 'https://malicious-domain.com/inject.js'
because it violates the following Content Security Policy directive:
"script-src 'self' https://cdn.shopify.com"

Before deploying a restrictive CSP to production, use Content-Security-Policy-Report-Only to log violations without blocking resources. This lets you identify any legitimate resources your policy would block.

Authentication and access control

Staff account security is frequently overlooked. We regularly audit stores where the owner account has no two-factor authentication, former employees still have active accounts, and multiple staff members share a single login. Each of these is a serious vulnerability.

Two-factor authentication enforcement

Every staff account with access to the Shopify admin should have two-factor authentication (2FA) enabled. Shopify supports authenticator apps (Google Authenticator, Authy, 1Password) and hardware security keys (YubiKey). Hardware keys provide the strongest protection against phishing attacks.

As of 2026, Shopify Plus stores can enforce 2FA for all staff accounts at the organisation level. Standard plan stores should establish a clear policy requiring 2FA and verify compliance during regular access reviews.

Permission structure

Shopify’s staff permissions system is granular. Use it:

/* Role-based permission examples */

// Customer service representative
Permissions: Orders (view, edit), Customers (view, edit), Products (view only)
No access: Settings, Themes, Apps, Analytics, Discounts

// Content manager
Permissions: Products (view, edit), Blog posts (full), Pages (full), Navigation (full)
No access: Orders, Customers, Settings, Apps

// Developer
Permissions: Themes (full), Apps (view), Online store (full)
No access: Financial data, Customer PII

// Store owner (only)
Full access including: Settings, Billing, Staff management, API credentials

Access review cadence

Conduct access reviews quarterly at minimum:

  • Remove accounts for staff who have left the organisation.
  • Downgrade permissions for staff who have changed roles.
  • Verify that 2FA is enabled on all active accounts.
  • Review collaborator accounts and remove those no longer needed.
  • Check app permissions and remove apps that are no longer in use.

PCI DSS compliance

Shopify’s PCI DSS Level 1 certification covers the platform’s checkout and payment infrastructure. As a merchant, you inherit this compliance for standard checkout flows. However, your obligations extend beyond what Shopify handles automatically.

What Shopify’s PCI compliance covers

  • Credit card data processing and storage during checkout.
  • Encryption of payment data in transit and at rest.
  • Secure checkout rendering isolated from theme code.
  • Tokenisation of stored payment methods for repeat purchases.

Your PCI responsibilities

Even with Shopify handling payment processing, merchants must ensure their custom code never inadvertently captures or transmits card data:

// DANGEROUS: Never capture payment form data with custom JavaScript
document.querySelector('#payment-form').addEventListener('submit', function(e) {
  // This would violate PCI compliance
  const cardNumber = document.querySelector('#card-number').value;
  fetch('/custom-endpoint', {
    body: JSON.stringify({ card: cardNumber })
  });
});

// CORRECT: Let Shopify's checkout handle all payment data
// Your custom code should never interact with payment form fields

If you use checkout customisations via Checkout Extensions, be particularly careful not to access or log payment field data. Shopify’s Checkout Extensibility framework sandboxes extensions from payment data, but poorly implemented custom scripts loaded through other means can violate PCI compliance.

PCI DSS compliance layers showing Shopify platform vs merchant responsibilities
PCI compliance is layered: Shopify handles payment infrastructure, but merchants must ensure custom code never captures or transmits card data.

Third-party app security vetting

Third-party apps are the most common attack vector for Shopify stores. Every app you install has the potential to access customer data, modify your store’s code, or introduce vulnerabilities. The Shopify App Store review process catches obvious issues, but it cannot guarantee that every app handles data responsibly or maintains its security over time.

Pre-installation checklist

  1. Review requested permissions — does the app request access proportional to its function? A product review app should not need access to customer financial data.
  2. Check the developer’s reputation — how long has the developer been on the App Store? How many other apps do they maintain? What do the reviews say about support responsiveness?
  3. Read the privacy policy — does the app explicitly state how it handles customer data? Does it share data with third parties? Is it GDPR compliant?
  4. Test in a development store — install the app in a test environment before production. Monitor the browser’s network tab to see what external requests the app makes.
  5. Check for GDPR compliance — does the app support Shopify’s mandatory GDPR webhooks (customer data request, customer data erasure, shop data erasure)?

Monitoring installed apps

// Use the browser's Performance API to monitor third-party script impact
const entries = performance.getEntriesByType('resource');
const thirdParty = entries.filter(e => !e.name.includes('cdn.shopify.com')
  && !e.name.includes(window.location.hostname));

console.table(thirdParty.map(e => ({
  name: e.name.split('/').pop(),
  domain: new URL(e.name).hostname,
  duration: Math.round(e.duration) + 'ms',
  size: Math.round(e.transferSize / 1024) + 'KB'
})));

Review your installed apps quarterly. Remove any that are no longer actively used. Unused apps still have API access and can still load scripts on your storefront — they represent risk without benefit.

Theme code security patterns

Custom theme code is the area where developers have the most direct security responsibility. Liquid templates, JavaScript, and CSS all present potential attack surfaces if not coded defensively.

Output encoding in Liquid

Shopify’s Liquid engine automatically HTML-encodes most output. However, there are contexts where encoding is bypassed or insufficient:

<!-- SAFE: Liquid auto-encodes in HTML context -->
<p>{{ product.title }}</p>

<!-- DANGEROUS: Unescaped output in JavaScript context -->
<script>
  var title = '{{ product.title }}';  // XSS if title contains quotes
</script>

<!-- SAFE: Use json filter for JavaScript context -->
<script>
  var title = {{ product.title | json }};  // Properly escaped
</script>

<!-- DANGEROUS: Raw HTML output -->
{{ product.description }}  <!-- Contains raw HTML from the editor -->

<!-- SAFER: Strip tags when displaying in sensitive contexts -->
{{ product.description | strip_html | truncate: 200 }}

Secure form handling

Shopify’s built-in forms (contact, newsletter) include CSRF protection automatically. But custom forms that post to external endpoints require additional care:

<!-- Always validate and sanitise on the server side -->
<!-- Never trust client-side validation alone -->

<!-- Use Shopify's form tag for built-in CSRF protection -->
{% form 'contact' %}
  <input type="email" name="contact[email]" required
    pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
    title="Enter a valid email address">
  <textarea name="contact[body]" maxlength="5000" required></textarea>
  <button type="submit">Send</button>
{% endform %}

Preventing clickjacking

Add frame protection to prevent your store from being embedded in malicious iframes:

<!-- Add to theme.liquid head -->
<meta http-equiv="X-Frame-Options" content="DENY">

<!-- Or via CSP (preferred) -->
frame-ancestors 'none';

For stores that use accessibility-compliant themes, security and accessibility requirements often overlap — both demand proper semantic HTML, validated forms, and predictable behaviour.

Customer data protection

GDPR, the UK Data Protection Act 2018, and PECR impose strict requirements on how you handle customer data. Shopify provides tools to help, but compliance is ultimately the merchant’s responsibility. This is closely related to GDPR technical compliance and should be considered alongside your broader privacy strategy.

Data minimisation

Only collect the customer data you actually need. Every additional data point you store increases your compliance burden and your risk exposure:

  • Do not collect date of birth unless required for age verification.
  • Do not store marketing preferences in custom metafields when Shopify’s built-in marketing consent system handles this.
  • Do not ask for phone numbers on forms that do not require them.
  • Regularly purge data you no longer need.

Secure data transmission

// When sending customer data to external systems, always use HTTPS
// and validate the destination

// BAD: HTTP endpoint for customer data
fetch('http://api.example.com/customers', {
  method: 'POST',
  body: JSON.stringify(customerData)
});

// GOOD: HTTPS with proper headers
fetch('https://api.example.com/customers', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + apiToken,
    'X-Request-ID': crypto.randomUUID()
  },
  body: JSON.stringify(customerData)
});

GDPR webhook implementation

Every Shopify app must handle three mandatory GDPR webhooks. If you build custom Shopify apps, implementing these is a legal requirement:

// Mandatory GDPR webhook handlers
app.post('/webhooks/customers/data_request', verifyShopifyWebhook, async (req, res) => {
  // Return all stored data for the requested customer
  const { customer } = req.body;
  const storedData = await getCustomerData(customer.id);
  // Send data to the specified email within 30 days
  await sendDataExport(customer.email, storedData);
  res.status(200).send();
});

app.post('/webhooks/customers/redact', verifyShopifyWebhook, async (req, res) => {
  // Delete all stored data for the requested customer
  const { customer } = req.body;
  await deleteCustomerData(customer.id);
  res.status(200).send();
});

app.post('/webhooks/shop/redact', verifyShopifyWebhook, async (req, res) => {
  // Delete all stored data for the uninstalled shop
  const { shop_domain } = req.body;
  await deleteShopData(shop_domain);
  res.status(200).send();
});
Customer data flow diagram showing secure handling practices
Customer data should flow through encrypted channels with minimal collection, proper consent, and clear retention policies.

Security monitoring and logging

You cannot protect what you cannot see. Security monitoring for Shopify stores focuses on detecting unusual access patterns, failed authentication attempts, and unexpected changes to store configuration.

Shopify’s built-in audit logging

Shopify Plus stores have access to activity logs through the Organisation settings. These logs capture:

  • Staff login events and failed authentication attempts.
  • Changes to store settings, themes, and navigation.
  • App installations and uninstallations.
  • API key creation and modification.
  • Changes to staff permissions.

Custom monitoring with webhooks

Set up Shopify Flow automations or webhook listeners to alert on suspicious activity:

// Webhook listener for app uninstall events
app.post('/webhooks/app/uninstalled', verifyShopifyWebhook, async (req, res) => {
  // Alert the team when any app is uninstalled
  await sendAlert({
    type: 'APP_UNINSTALLED',
    shop: req.body.shop_domain,
    timestamp: new Date().toISOString()
  });
  res.status(200).send();
});

// Monitor for bulk data access patterns
app.post('/webhooks/bulk_operations/finish', verifyShopifyWebhook, async (req, res) => {
  const { admin_graphql_api_id, status, type } = req.body;
  if (type === 'customers' || type === 'orders') {
    await sendAlert({
      type: 'BULK_DATA_EXPORT',
      resource: type,
      status: status,
      timestamp: new Date().toISOString()
    });
  }
  res.status(200).send();
});

Client-side error monitoring

Implement error monitoring to catch client-side security issues in your theme code:

// Report CSP violations
document.addEventListener('securitypolicyviolation', function(e) {
  const violation = {
    directive: e.violatedDirective,
    blocked: e.blockedURI,
    source: e.sourceFile,
    line: e.lineNumber,
    timestamp: new Date().toISOString()
  };
  // Send to your logging service
  navigator.sendBeacon('/api/csp-report', JSON.stringify(violation));
});

Incident response planning

Every Shopify store should have an incident response plan. The plan does not need to be complex, but it must exist and key staff must know how to execute it. When a security incident occurs, speed and clarity of response make the difference between a contained event and a catastrophic breach.

Incident response steps

  1. Identify — confirm the incident is genuine. Not every anomaly is a breach.
  2. Contain — limit the impact. Rotate compromised credentials, disable compromised accounts, remove malicious code.
  3. Eradicate — remove the root cause. Update vulnerable code, remove compromised apps, patch the entry point.
  4. Recover — restore normal operations. Verify that the fix is effective. Monitor for recurrence.
  5. Report — notify affected parties as required. Under GDPR, you must report qualifying breaches to the ICO within 72 hours.
  6. Review — conduct a post-incident review. Document what happened, why, and what changes will prevent recurrence.

Emergency credential rotation

# Emergency credential rotation checklist

1. Shopify Admin API tokens
   - Settings > Apps and sales channels > Develop apps
   - Rotate each custom app's Admin API access token
   - Update all systems that use the old tokens

2. Storefront API tokens
   - Generate new Storefront API tokens
   - Update headless storefronts and mobile apps

3. Staff passwords
   - Force password resets for all staff accounts
   - Verify 2FA is enabled on all accounts

4. Third-party service credentials
   - Rotate API keys for Klaviyo, Google, shipping providers
   - Update credentials in all integration points

5. Webhook signatures
   - Regenerate webhook signing secrets
   - Update webhook verification in all listeners
Incident response workflow showing the six phases
A clear incident response plan ensures rapid containment and recovery. The 72-hour GDPR reporting window makes preparation essential.

Regular security audits

Schedule security reviews at least twice per year. The audit should cover:

  • Staff account review (active accounts, permissions, 2FA status).
  • App audit (installed apps, their permissions, last update date, current necessity).
  • API credential inventory (all active credentials, their scopes, last rotation date).
  • CSP review (new third-party scripts added, unnecessary entries, policy effectiveness).
  • Theme code review (new custom code, Liquid output safety, JavaScript security).
  • Webhook endpoint security (HMAC verification, HTTPS enforcement, error handling).

Security is not a project with a completion date. It is an ongoing discipline. The stores that maintain the strongest security posture are those that treat security reviews as a regular operational task, not an annual compliance exercise. If you want help auditing your store’s security posture, get in touch — we include security reviews as part of our ongoing Shopify development retainers.