StackMap.aiIntegration Hub
Back to integrations
E-Commerce & CRM#Magento#Salesforce#E-commerce#CRM#Automated Sync

How to Connect Magento to Salesforce Setup Blueprint

Verified Blueprint

Provides a robust, real-time synchronization blueprint for pushing customer and order data from Magento to Salesforce.

Magento
Salesforce
Alternative Flow

Need an alternative to manual coding? Connect these apps in minutes via Make.com.

Try Make.com

How to Connect Magento to Salesforce (Automated Data Sync)

📊 Integration Overview This blueprint outlines a technical integration pipeline designed to synchronize critical e-commerce data, specifically customer and order information, from Magento to Salesforce in real-time. The core objective is to provide sales teams with immediate access to up-to-date customer profiles and purchase histories, enabling more informed engagement and streamlined sales processes. When a new order is placed or an existing order is updated in Magento, a webhook event triggers the pipeline. The payload is then transformed and mapped to appropriate Salesforce objects, such as Leads, Opportunities, Accounts, or Contacts, ensuring a unified view of the customer journey across both platforms. This automation reduces manual data entry, minimizes errors, and accelerates the sales cycle by providing timely insights directly within the CRM.

Available integrations in directory: "magento-to-quickbooks", "magento-to-xero", ["shopify-to-freshbooks"], "shopify-to-hubspot", ["shopify-to-klaviyo"], ["shopify-to-mailchimp"], ["shopify-to-netsuite"], ["shopify-to-quickbooks"], "shopify-to-salesforce", ["shopify-to-waveaccounting"], ["shopify-to-xero"], ["shopify-to-zohocrm"], ["stripe-to-hubspot"], "woocommerce-to-hubspot", ["woocommerce-to-klaviyo"], ["woocommerce-to-mailchimp"], ["woocommerce-to-netsuite"], ["woocommerce-to-quickbooks"], "woocommerce-to-salesforce", ["woocommerce-to-waveaccounting"], ["woocommerce-to-xero"], ["woocommerce-to-zohocrm"].

🛠️ Core Connection Requirements Primary Key: order_id (Magento) / External_Order_ID__c (Salesforce Custom Field) Trigger Event: New Order Created in Magento Action Event: Create or Update Opportunity or Lead in Salesforce

📋 The 5-Step Execution Blueprint

Step 1: Authentication & Scope Configuration Securely establish API access for both Magento and Salesforce. For Magento, acquire a Consumer Key, Consumer Secret, Access Token, and Access Token Secret via the Magento Admin Panel (System > Integrations). For Salesforce, set up a Connected App (Platform Tools > Apps > App Manager) to obtain a Client ID and Client Secret, enabling OAuth 2.0 JWT Bearer Token flow or Web Server Flow. Ensure the necessary OAuth scopes are granted for Salesforce, typically api, full, refresh_token.

# Magento API Credentials
MAGENTO_BASE_URL="https://your-magento-store.com"
MAGENTO_CONSUMER_KEY="your_magento_consumer_key"
MAGENTO_CONSUMER_SECRET="your_magento_consumer_secret"
MAGENTO_ACCESS_TOKEN="your_magento_access_token"
MAGENTO_ACCESS_TOKEN_SECRET="your_magento_access_token_secret"
MAGENTO_WEBHOOK_SECRET="your_magento_webhook_hmac_secret" # Used for webhook signature validation

# Salesforce API Credentials
SALESFORCE_CLIENT_ID="your_salesforce_client_id"
SALESFORCE_CLIENT_SECRET="your_salesforce_client_secret"
SALESFORCE_USERNAME="your_salesforce_username" # For JWT flow
SALESFORCE_PRIVATE_KEY_PATH="/path/to/your/server.key" # For JWT flow
SALESFORCE_LOGIN_URL="https://login.salesforce.com" # Or https://test.salesforce.com for sandbox
SALESFORCE_API_VERSION="v58.0"

Step 2: Webhook Trigger Setup Register a webhook in your Magento instance that listens for sales_order_save_after events. This ensures that any new order or significant update to an existing order triggers the synchronization process. The webhook payload will be sent to a designated endpoint in your integration service. Implement robust security by validating the incoming webhook's cryptographic signature using the shared secret configured in Magento.

import * as express from 'express';
import * as crypto from 'crypto';
import { Request, Response } from 'express';

const app = express();
const WEBHOOK_SECRET = process.env.MAGENTO_WEBHOOK_SECRET || 'super_secret_key'; // Use a strong, random key

// Middleware to parse raw body for signature validation
app.use(express.json({
  verify: (req: Request, res: Response, buf: Buffer) => {
    (req as any).rawBody = buf;
  }
}));

app.post('/magento/webhook', (req: Request, res: Response) => {
  const hmacHeader = req.get('x-magento-signature');

  if (!hmacHeader) {
    console.error('Webhook received without X-Magento-Signature header.');
    return res.status(401).send('Unauthorized: Missing signature.');
  }

  // Magento typically sends 'sha256=<signature>'
  const [algorithm, signature] = hmacHeader.split('=');

  if (algorithm !== 'sha256') {
    console.error(`Unsupported signature algorithm: ${algorithm}`);
    return res.status(400).send('Bad Request: Unsupported signature algorithm.');
  }

  const expectedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update((req as any).rawBody)
    .digest('hex');

  if (signature !== expectedSignature) {
    console.error('Webhook signature mismatch.');
    return res.status(401).send('Unauthorized: Invalid signature.');
  }

  console.log('Webhook signature validated successfully.');
  const orderData = req.body;
  console.log('Received Magento Order Data:', orderData);

  // Process orderData asynchronously (e.g., push to a message queue)
  // await someQueueService.addOrderToQueue(orderData);

  res.status(200).send('Webhook received and validated.');
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Webhook listener running on port ${PORT}`);
});

Step 3: Payload Transformation & Mapping Once the Magento webhook payload is received and validated, it needs to be transformed into a structure compatible with Salesforce's API. This involves mapping Magento order fields (e.g., increment_id, customer_email, grand_total, status, items) to corresponding Salesforce object fields (e.g., Name, Amount, StageName, CloseDate for an Opportunity, or Email, FirstName, LastName for a Lead/Contact). Custom fields in Salesforce (e.g., Magento_Order_ID__c) are often used to store the original Magento order_id for idempotency and traceability.

{
  "magento_input": {
    "event": "sales_order_save_after",
    "order": {
      "entity_id": 12345,
      "increment_id": "000000123",
      "store_id": 1,
      "state": "new",
      "status": "pending",
      "grand_total": 99.99,
      "base_grand_total": 99.99,
      "customer_email": "jane.doe@example.com",
      "customer_firstname": "Jane",
      "customer_lastname": "Doe",
      "billing_address": {
        "firstname": "Jane",
        "lastname": "Doe",
        "street": ["123 Main St"],
        "city": "Anytown",
        "region": "State",
        "postcode": "12345",
        "country_id": "US",
        "telephone": "555-123-4567"
      },
      "items": [
        {
          "item_id": 1,
          "sku": "PROD-XYZ",
          "name": "Product X",
          "qty_ordered": 1,
          "price": 99.99
        }
      ],
      "created_at": "2023-10-26 10:00:00",
      "updated_at": "2023-10-26 10:05:00"
    }
  },
  "salesforce_output": {
    "sobjectType": "Opportunity",
    "Name": "Order 000000123 - Jane Doe",
    "Amount": 99.99,
    "StageName": "Prospecting",
    "CloseDate": "2023-11-26",
    "Magento_Order_ID__c": "000000123",
    "Magento_Customer_Email__c": "jane.doe@example.com",
    "Billing_Street__c": "123 Main St",
    "Billing_City__c": "Anytown",
    "Billing_State__c": "State",
    "Billing_PostalCode__c": "12345",
    "Billing_Country__c": "US",
    "Description": "Product X (SKU: PROD-XYZ, Qty: 1)",
    "LeadSource": "Magento E-commerce"
    // Potentially associate with an existing Account/Contact based on email
    // "AccountId": "001xxxxxxxxxxxxxxx"
  }
}

Step 4: Endpoint Despatch & Error Guarding Dispatch the transformed payload to the Salesforce REST API. Implement robust error handling for common HTTP status codes. For high-volume scenarios, an asynchronous message queue (e.g., Redis with BullMQ) is recommended to buffer requests and manage retries.

  • 401 Unauthorized (Authentication Error): If the access token is invalid or expired, initiate a token refresh flow using the stored refresh token or re-authenticate using the JWT bearer token flow. If refresh fails, alert an administrator.
  • 400 Bad Request (Invalid Data): Log the specific validation errors returned by Salesforce (e.g., missing required fields, incorrect data types). These errors often indicate an issue in the payload transformation step. The message should be routed to a dead-letter queue for manual inspection and correction.
  • 429 Too Many Requests (Rate Limiting): Salesforce enforces API rate limits. Implement an exponential backoff strategy with jitter for retries. If using a message queue, the message should be re-queued with a delay. Consider dynamic adjustment of worker concurrency based on observed rate limit responses.
  • 5xx Server Errors (Salesforce Internal Issues): Implement a robust retry mechanism with exponential backoff. If repeated retries fail, move the message to a dead-letter queue and trigger an alert.
  • Success (2xx codes): Log the successful creation/update, including the Salesforce record ID, for audit and traceability.
import axios from 'axios';
import { SalesforceAuth } from './salesforce-auth-service'; // Assumed service for token management
import { delay } from './utils'; // Utility for introducing delays

const SALESFORCE_API_URL = `${process.env.SALESFORCE_LOGIN_URL}/services/data/${process.env.SALESFORCE_API_VERSION}`;

interface SalesforcePayload {
  sobjectType: string;
  [key: string]: any;
}

async function createOrUpdateSalesforceOpportunity(payload: SalesforcePayload): Promise<string | undefined> {
  let accessToken = await SalesforceAuth.getAccessToken();
  const maxRetries = 5;
  let attempt = 0;

  while (attempt < maxRetries) {
    try {
      // First, check for existing Opportunity using Magento_Order_ID__c
      const query = `SELECT Id FROM Opportunity WHERE Magento_Order_ID__c = '${payload.Magento_Order_ID__c}' LIMIT 1`;
      const searchResponse = await axios.get(`${SALESFORCE_API_URL}/query`, {
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        },
        params: { q: query }
      });

      if (searchResponse.data.records.length > 0) {
        const existingOpportunityId = searchResponse.data.records[0].Id;
        console.log(`Opportunity with Magento Order ID ${payload.Magento_Order_ID__c} already exists: ${existingOpportunityId}. Updating...`);
        // Update existing record
        const updateResponse = await axios.patch(`${SALESFORCE_API_URL}/sobjects/Opportunity/${existingOpportunityId}`, payload, {
          headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json'
          }
        });
        console.log('Salesforce Opportunity updated:', updateResponse.data);
        return existingOpportunityId;
      } else {
        console.log(`Creating new Opportunity for Magento Order ID ${payload.Magento_Order_ID__c}...`);
        // Create new record
        const createResponse = await axios.post(`${SALESFORCE_API_URL}/sobjects/Opportunity`, payload, {
          headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json'
          }
        });
        console.log('Salesforce Opportunity created:', createResponse.data);
        return createResponse.data.id;
      }

    } catch (error: any) {
      if (error.response) {
        const statusCode = error.response.status;
        const errorBody = error.response.data;
        console.error(`Salesforce API Error (${statusCode}):`, errorBody);

        switch (statusCode) {
          case 401: // Unauthorized - token expired or invalid
            console.warn('Salesforce token expired or invalid. Attempting to refresh...');
            accessToken = await SalesforceAuth.refreshAccessToken(); // Assumed function
            if (accessToken) {
              attempt++;
              await delay(1000 * Math.pow(2, attempt)); // Exponential backoff
              continue; // Retry with new token
            } else {
              console.error('Failed to refresh Salesforce access token. Manual intervention required.');
              throw new Error('Salesforce authentication failed.');
            }
          case 400: // Bad Request - invalid data
            console.error('Bad Request to Salesforce API. Data validation error:', errorBody);
            // Log to dead-letter queue, alert administrator
            throw new Error(`Salesforce Bad Request: ${JSON.stringify(errorBody)}`);
          case 429: // Rate Limit Exceeded
            console.warn('Salesforce API rate limit exceeded. Retrying with exponential backoff...');
            attempt++;
            await delay(1000 * Math.pow(2, attempt) + Math.random() * 1000); // Exponential backoff with jitter
            break; // Loop to retry
          case 500: // Internal Server Error
          case 503: // Service Unavailable
            console.warn('Salesforce server error. Retrying with exponential backoff...');
            attempt++;
            await delay(1000 * Math.pow(2, attempt)); // Exponential backoff
            break; // Loop to retry
          default:
            console.error(`Unhandled Salesforce API error: ${statusCode} - ${JSON.stringify(errorBody)}`);
            throw new Error(`Unhandled Salesforce API error: ${JSON.stringify(errorBody)}`);
        }
      } else {
        console.error('Network or unknown error connecting to Salesforce:', error.message);
        throw error;
      }
    }
  }
  console.error(`Failed to process Salesforce request after ${maxRetries} attempts.`);
  return undefined;
}

Step 5: Live Loop Validation Thoroughly test the integration in a sandbox environment.

  1. Magento Sandbox Order: Create a new order in your Magento development or staging environment. Ensure the webhook is correctly configured to fire.
  2. Monitor Integration Service: Observe the logs of your integration service to confirm the webhook payload is received, validated, and transformed successfully.
  3. Salesforce Sandbox Verification: Log in to your Salesforce sandbox instance.
    • Search: Use the Magento order_id (stored in the custom Magento_Order_ID__c field) to search for the newly created or updated Lead/Opportunity.
    • Data Integrity: Verify that all mapped fields (e.g., Name, Amount, Stage, CloseDate, Email, Billing Address) are accurately populated without truncation or data type mismatches.
    • Duplication Check: Create a second order in Magento with similar customer details but a different order ID. Confirm that a new distinct record is created in Salesforce, or if an existing customer record is updated (depending on your specific logic for customer handling).
    • Edge Cases: Test with different order statuses, products, and customer types to ensure robustness.

❓ Integration Frequently Asked Questions

Q: How does this pipeline handle duplicate data entries? A: To prevent duplicate data entries in Salesforce, the pipeline implements an idempotency check before creating new records. When an order webhook is received from Magento, the integration service first queries Salesforce to check for the existence of an Opportunity or Lead that corresponds to that specific Magento order. This is typically done by searching a custom field, such as Magento_Order_ID__c, which stores the unique increment_id from Magento. If a record with the matching Magento_Order_ID__c is found, the existing record is updated with the latest order information. If no matching record is found, a new Opportunity or Lead is created. For customer-related objects (Account/Contact), a similar check can be performed using the customer_email as the primary key. This ensures that only one Salesforce record represents a unique Magento order, maintaining data integrity.

Q: What happens if the API rate limit is exceeded during high volume? A: During periods of high transaction volume, the Salesforce API rate limits can be exceeded. To address this, the integration pipeline employs several strategies:

  1. Asynchronous Queueing: Incoming Magento webhook payloads are immediately placed into a robust message queue system (e.g., built with Redis and BullMQ). This decouples the webhook reception from the Salesforce API call, preventing data loss and allowing the integration service to handle spikes in traffic gracefully.
  2. Worker Pool: Dedicated worker processes consume messages from the queue. Each worker is responsible for transforming the payload and making API calls to Salesforce.
  3. Exponential Backoff & Retries: When a Salesforce API call returns a 429 Too Many Requests status, the message is automatically re-queued with an exponential backoff delay. This means the time between retries increases, giving the Salesforce API time to recover. Jitter (a small random delay) is often added to the backoff to prevent a "thundering herd" problem where many workers retry simultaneously.
  4. Circuit Breaker Pattern: Beyond a certain number of failed retries for rate limiting, a circuit breaker can temporarily halt attempts to send data to Salesforce for a predefined period. This prevents continuous hammering of an overloaded API and allows the system to recover. Messages affected by an open circuit breaker may be moved to a dead-letter queue for manual intervention or delayed processing once the circuit closes.
  5. Configurable Concurrency: The number of concurrent workers or API requests per second can be dynamically configured and adjusted based on observed rate limit responses and Salesforce's limits for the specific organization.
Developer Infrastructure

Deploy custom integration scripts safely.

Get $200 free server credits on DigitalOcean to host webhook brokers, queues, and database engines.

Get $200 Free Credits

Integration Core Specs

Source Platform

Magento

Destination Platform

Salesforce

Primary Key Identifieremail
Pipeline SpeedSub-second Realtime

Production Guardrails

  • Automatic signature checks for HMAC SHA256 payloads.
  • Redis queue throttle buffers to prevent Intuit/HubSpot API caps.
  • Fallbacks for missing SKU or contact mappings.
  • Idempotent validation gates before REST ledger entry creation.