Skip to content

Troubleshooting

Learn how to diagnose and fix common issues with the Google Pay web component.

Exception types and error codes

Component exceptions

The Google Pay web component throws specific exceptions for different error scenarios:

Exception Error CodeDescription
GooglePayLoadFailedExceptionSDK0704The Google Pay API failed to load. For example, due to network issues, blocked resources, or CSP restrictions.
GooglePayNotReadyExceptionSDK0701Google Pay isn't ready on this device or browser. For example, unsupported browser, no Google account, or no payment methods configured.
GooglePayClientNotInitializedExceptionSDK0703The Google Pay client was not properly initialised before attempting a payment.
GooglePayConfigurationValidationFailedExceptionSDK0705Configuration validation failed. For example, missing required fields, invalid payment method configuration, or incorrect format.
GooglePayPaymentFailedExceptionSDK0702Payment processing failed. For example, due to network issues, declined payment, or server errors.
GooglePayDecryptAndTokenVaultFailedExceptionSDK0706Payment token decryption or vault storage failed. Check gateway configuration and token handling.
UnsupportedFundingTypeGooglePaySdkExceptionSDK0110Google Pay is not included in the allowed funding types for this session.

Payment cancellation by the user is not thrown as an exception. Instead, use the onCancel callback to handle user cancellations gracefully.

Error handling best practices

Comprehensive error handler

const config = {
  onError: (error) => {
    // Log error for debugging
    console.error('Google Pay error:', {
      name: error.name,
      message: error.message,
      code: error.ErrorCode, // Note: Capital 'E' in ErrorCode
      stack: error.stack,
      timestamp: new Date().toISOString()
    });

    // Handle specific error types by exception name
    if (error.name === 'GooglePayNotReadyException') {
      showUserMessage('Google Pay is not available on this device. Please use an alternative payment method.');
      showAlternativePaymentMethods();
      
    } else if (error.name === 'GooglePayConfigurationValidationFailedException') {
      showUserMessage('Payment system temporarily unavailable. Please try again in a few moments.');
      logCriticalError('Configuration validation error', error);
      
    } else if (error.name === 'GooglePayClientNotInitializedException') {
      showUserMessage('Payment system not ready. Please refresh and try again.');
      logCriticalError('Client not initialized', error);
      
    } else if (error.name === 'GooglePayLoadFailedException') {
      showUserMessage('Unable to load payment system. Please check your connection and try again.');
      offerRetryOption();
      
    } else if (error.name === 'GooglePayPaymentFailedException') {
      showUserMessage('Payment failed. Please check your payment information and try again.');
      offerRetryOption();
      
    } else if (error.name === 'GooglePayDecryptAndTokenVaultFailedException') {
      showUserMessage('Payment processing error. Please try again.');
      logCriticalError('Token vault error', error);
      
    } else {
      showUserMessage('An unexpected error occurred. Please try again or contact support.');
      logUnknownError(error);
    }
  },
  
  // Handle user cancellation separately (not an exception)
  onCancel: () => {
    console.log('User cancelled Google Pay');
    trackEvent('google_pay_cancelled');
  }
};

function showUserMessage(message) {
  const errorDiv = document.createElement('div');
  errorDiv.className = 'error-message';
  errorDiv.textContent = message;
  document.getElementById('payment-container').appendChild(errorDiv);
  
  // Auto-dismiss after 5 seconds
  setTimeout(() => {
    errorDiv.remove();
  }, 5000);
}

function logCriticalError(context, error) {
  // Send to error monitoring service
  if (window.errorReporting) {
    window.errorReporting.captureException(error, { context });
  }
}

Troubleshooting common issues

Google Pay button isn't showing

The symptoms of this are:

  • The button element is hidden or not rendered.
  • There's an empty container where the button should appear.
  • No Google Pay option is visible to customers.

Diagnostic steps

// Step 1: Check Google Pay availability
console.log('Checking Google Pay availability...');

// Check if Google Pay API is loaded
if (!window.google || !window.google.payments || !window.google.payments.api) {
  console.error('Google Pay API not loaded');
  console.log('Ensure the Google Pay script is included and loaded');
  return;
}

// Step 2: Check browser compatibility
const browserInfo = {
  userAgent: navigator.userAgent,
  isChrome: /Chrome\/(\d+)/.test(navigator.userAgent),
  isSafari: /Safari\//.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent),
  isFirefox: /Firefox\/(\d+)/.test(navigator.userAgent)
};
console.log('Browser info:', browserInfo);

// Step 3: Check HTTPS
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
  console.error('Google Pay requires HTTPS in production');
  return;
}

// Step 4: Verify payment method configuration
const paymentMethod = config.paymentDataRequest.allowedPaymentMethods[0];
  
if (!paymentMethod || !paymentMethod.parameters) {
  console.error('Payment method configuration is missing');
  return;
}

console.log('Allowed card networks:', paymentMethod.parameters.allowedCardNetworks);
console.log('Allowed auth methods:', paymentMethod.parameters.allowedAuthMethods);

// Note: The SDK automatically configures tokenizationSpecification from the session

// Step 5: Test Google Pay readiness
try {
  const paymentsClient = new google.payments.api.PaymentsClient({
    environment: 'TEST'
  });
  
  const isReadyToPayRequest = {
    apiVersion: 2,
    apiVersionMinor: 0,
    allowedPaymentMethods: config.paymentDataRequest.allowedPaymentMethods
  };
  
  paymentsClient.isReadyToPay(isReadyToPayRequest)
    .then(response => {
      if (response.result) {
        console.log('✅ Google Pay is ready');
      } else {
        console.warn('⚠️ Google Pay is not ready - user may not have payment methods configured');
      }
    })
    .catch(error => {
      console.error('❌ Google Pay readiness check failed:', error);
    });
    
} catch (error) {
  console.error('Failed to check Google Pay readiness:', error);
}

console.log('All diagnostic checks complete');

Solutions

// Solution 1: Graceful fallback
function initializeGooglePay() {
  if (checkGooglePayAvailability()) {
    renderGooglePayButton();
  } else {
    console.log('Google Pay not available, showing alternatives');
    renderAlternativePaymentMethods();
  }
}

function checkGooglePayAvailability() {
  return window.google && 
         window.google.payments && 
         window.google.payments.api &&
         isHttps() &&
         hasValidPaymentMethods();
}

function isHttps() {
  return location.protocol === 'https:' || location.hostname === 'localhost';
}

function hasValidPaymentMethods() {
  const paymentMethods = config.paymentDataRequest?.allowedPaymentMethods;
  return paymentMethods && 
         paymentMethods.length > 0 && 
         paymentMethods[0].parameters?.allowedCardNetworks?.length > 0;
}

function renderAlternativePaymentMethods() {
  const container = document.getElementById('payment-buttons');
  container.innerHTML = `
    <button class="credit-card-button">Pay with Credit Card</button>
    <button class="paypal-button">Pay with PayPal</button>
  `;
}

// Solution 2: Progressive loading
function loadGooglePayWithFallback() {
  const timeout = setTimeout(() => {
    console.warn('Google Pay API loading timeout');
    renderAlternativePaymentMethods();
  }, 5000); // 5 second timeout
  
  // Load Google Pay API
  const script = document.createElement('script');
  script.src = 'https://pay.google.com/gp/p/js/pay.js';
  script.async = true;
  
  script.onload = () => {
    clearTimeout(timeout);
    console.log('Google Pay API loaded successfully');
    initializeGooglePay();
  };
  
  script.onerror = () => {
    clearTimeout(timeout);
    console.error('Failed to load Google Pay API');
    renderAlternativePaymentMethods();
  };
  
  document.head.appendChild(script);
}

Payment sheet not opening

The symptoms of this are:

  • Button is visible and clickable but nothing happens.
  • No error messages are shown.
  • Payment sheet doesn't appear after button click.

Diagnostic steps

// Enhanced button click handler with diagnostics
const googlePayConfig = {
  onGooglePaymentButtonClicked: async (event) => {
    console.group('🔍 Google Pay Button Click Diagnostics');
    
    // Check 1: Verify button was actually clicked
    console.log('Button clicked:', event);
    
    // Check 2: Verify configuration
    console.log('Payment request config:', googlePayConfig.paymentDataRequest);
    
    // Check 3: Verify Google Pay client
    if (!window.google || !window.google.payments || !window.google.payments.api) {
      console.error('❌ Google Pay API not available');
      console.groupEnd();
      return;
    }
    
    // Check 4: Test payment data request
    try {
      const paymentsClient = new google.payments.api.PaymentsClient({
        environment: pxpSdk.environment === 'live' ? 'PRODUCTION' : 'TEST'
      });
      
      // Validate payment data request
      console.log('Testing payment data request...');
      const testRequest = {
        apiVersion: 2,
        apiVersionMinor: 0,
        allowedPaymentMethods: googlePayConfig.paymentDataRequest.allowedPaymentMethods
      };
      
      const readyToPay = await paymentsClient.isReadyToPay(testRequest);
      console.log('Ready to pay:', readyToPay);
      
      if (!readyToPay.result) {
        console.error('❌ Google Pay not ready - no payment methods configured');
      }
      
    } catch (error) {
      console.error('❌ Payment request test failed:', error);
    }
    
    console.groupEnd();
  }
};

Solutions

// Solution 1: Add validation before opening sheet
const googlePayConfig = {
  onCustomValidation: async () => {
    console.log('Running custom validation...');
    
    const validations = [
      {
        name: 'Email',
        test: () => {
          const email = document.getElementById('email')?.value;
          return email && email.includes('@');
        },
        message: 'Please enter a valid email address'
      },
      {
        name: 'Terms',
        test: () => document.getElementById('terms')?.checked,
        message: 'Please accept terms and conditions'
      },
      {
        name: 'Amount',
        test: () => {
          const amount = parseFloat(googlePayConfig.paymentDataRequest.transactionInfo.totalPrice);
          return amount > 0;
        },
        message: 'Invalid payment amount'
      }
    ];
    
    for (const validation of validations) {
      if (!validation.test()) {
        console.error(`Validation failed: ${validation.name}`);
        showError(validation.message);
        return false;
      }
      console.log(`✅ ${validation.name} validation passed`);
    }
    
    return true;
  }
};

// Solution 2: Handle configuration errors
function createGooglePayButton() {
  try {
    // Validate configuration before creating button
    validateGooglePayConfiguration(googlePayConfig);
    
    const googlePayButton = pxpSdk.create('google-pay-button', googlePayConfig);
    googlePayButton.mount('google-pay-container');
    
    console.log('✅ Google Pay button created successfully');
    
  } catch (error) {
    console.error('❌ Failed to create Google Pay button:', error);
    
    if (error.name === 'GooglePayConfigurationValidationFailedException') {
      showError('Payment configuration error. Please contact support.');
      logConfigurationError(error);
    } else {
      showError('Unable to initialise Google Pay. Please try again.');
    }
    
    // Show alternative payment methods
    showAlternativePaymentMethods();
  }
}

function validateGooglePayConfiguration(config) {
  if (!config.paymentDataRequest) {
    throw new Error('paymentDataRequest is required');
  }
  
  if (!config.paymentDataRequest.transactionInfo) {
    throw new Error('transactionInfo is required');
  }
  
  if (!config.paymentDataRequest.allowedPaymentMethods || 
      config.paymentDataRequest.allowedPaymentMethods.length === 0) {
    throw new Error('allowedPaymentMethods is required');
  }
  
  const amount = parseFloat(config.paymentDataRequest.transactionInfo.totalPrice);
  if (isNaN(amount) || amount <= 0) {
    throw new Error('Invalid transaction amount');
  }
}

Payment authorisation failures

The symptoms of this are:

  • The Google Pay sheet appears but payment fails.
  • Customer sees a generic error message.
  • Transaction doesn't complete successfully.

Diagnostic steps

// Enhanced authorisation handler with detailed logging
const googlePayConfig = {
  onPreAuthorisation: async (data) => {
    console.group('💳 Payment Authorisation Diagnostics');
    
    console.log('Pre-authorisation data:', {
      hasData: !!data,
      billingAddress: data?.billingAddress ? 'Present' : 'Missing',
      timestamp: new Date().toISOString()
    });
    
    try {
      // Validate amount
      const amount = getOrderTotal();
      console.log('Transaction amount:', amount);
      
      if (amount <= 0) {
        console.error('❌ Invalid amount:', amount);
        throw new Error('Invalid transaction amount');
      }
      
      // Check inventory
      console.log('Checking inventory...');
      const inventoryAvailable = await checkInventory();
      console.log('Inventory available:', inventoryAvailable);
      
      if (!inventoryAvailable) {
        console.error('❌ Inventory not available');
        throw new Error('Items no longer available');
      }
      
      console.log('✅ Pre-authorisation checks passed');
      console.groupEnd();
      
      return {
        riskScreeningData: {
          performRiskScreening: true
        }
      };
      
    } catch (error) {
      console.error('❌ Pre-authorisation failed:', error);
      console.groupEnd();
      return null; // Cancel payment
    }
  },
  
  onPostAuthorisation: async (result, paymentData) => {
    console.group('📊 Payment Authorisation Result');
    
    const isSuccess = 'merchantTransactionId' in result;
    console.log('Result type:', isSuccess ? 'Success (MerchantSubmitResult)' : 'Failure (FailedSubmitResult)');
    console.log('Transaction IDs:', {
      merchantTransactionId: result.merchantTransactionId,
      systemTransactionId: result.systemTransactionId
    });
    
    if (!isSuccess && 'errorCode' in result) {
      console.error('Payment not authorized:', {
        errorCode: result.errorCode,
        errorReason: result.errorReason,
        correlationId: result.correlationId
      });
    } else if (isSuccess) {
      console.log('✅ Payment authorized successfully');
    }
    
    console.groupEnd();
    
    // Handle result...
  }
};

Solutions

// Solution 1: Enhanced validation
function validatePaymentData(paymentData) {
  const validations = [
    {
      check: () => paymentData && Object.keys(paymentData).length > 0,
      error: 'Payment data is missing'
    },
    {
      check: () => {
        const amount = getOrderTotal();
        return amount > 0 && amount < 1000000;
      },
      error: 'Invalid payment amount'
    },
    {
      check: () => getCurrentCustomerEmail(),
      error: 'Customer email is required'
    }
  ];
  
  for (const validation of validations) {
    if (!validation.check()) {
      throw new Error(validation.error);
    }
  }
}

// Solution 2: Implement retry logic
async function processPaymentWithRetry(paymentData, maxRetries = 2) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`Payment attempt ${attempt} of ${maxRetries}`);
      
      const result = await processPayment(paymentData);
      
      console.log('Payment processed successfully');
      return result;
      
    } catch (error) {
      console.warn(`Payment attempt ${attempt} failed:`, error.message);
      
      if (isRetryableError(error) && attempt < maxRetries) {
        console.log(`Retrying payment...`);
        await delay(1000 * attempt); // Progressive delay
        continue;
      }
      
      console.error('Payment failed after all retries');
      throw error;
    }
  }
}

function isRetryableError(error) {
  const retryableErrors = [
    'network error',
    'timeout',
    'temporary failure',
    'service unavailable'
  ];
  
  return retryableErrors.some(retryableError => 
    error.message.toLowerCase().includes(retryableError)
  );
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Shipping address errors

The symptoms of this are:

  • Customer selects shipping address but sees error.
  • Unable to calculate shipping costs.
  • Address validation failures.

Diagnostic steps

const googlePayConfig = {
  onPaymentDataChanged: async (intermediatePaymentData) => {
    console.group('📍 Shipping Address Diagnostics');
    
    const address = intermediatePaymentData.shippingAddress;
    console.log('Shipping address:', address);
    
    if (!address) {
      console.warn('⚠️ No shipping address provided');
      console.groupEnd();
      return {};
    }
    
    // Validate address fields
    const requiredFields = ['countryCode', 'postalCode', 'administrativeArea'];
    const missingFields = requiredFields.filter(field => !address[field]);
    
    if (missingFields.length > 0) {
      console.error('❌ Missing address fields:', missingFields);
    } else {
      console.log('✅ All required address fields present');
    }
    
    // Test shipping calculation
    try {
      console.log('Testing shipping calculation...');
      const shippingCost = await calculateShippingCost(address);
      console.log('Shipping cost calculated:', shippingCost);
    } catch (error) {
      console.error('❌ Shipping calculation failed:', error);
    }
    
    console.groupEnd();
    
    // Return actual response...
  }
};

Solutions

const googlePayConfig = {
  onPaymentDataChanged: async (intermediatePaymentData) => {
    try {
      const address = intermediatePaymentData.shippingAddress;
      
      if (!address) {
        return {};
      }
      
      // Validate address completeness
      if (!address.countryCode || !address.postalCode) {
        return {
          error: {
            reason: 'SHIPPING_ADDRESS_INVALID',
            message: 'Please enter a complete address',
            intent: 'SHIPPING_ADDRESS'
          }
        };
      }
      
      // Check if we ship to this country
      const allowedCountries = ['US', 'CA', 'GB', 'FR', 'DE'];
      if (!allowedCountries.includes(address.countryCode)) {
        return {
          error: {
            reason: 'SHIPPING_ADDRESS_UNSERVICEABLE',
            message: `We do not ship to ${address.countryCode}`,
            intent: 'SHIPPING_ADDRESS'
          }
        };
      }
      
      // Calculate shipping with error handling
      let shippingCost = 0;
      try {
        shippingCost = await calculateShippingCost(address);
      } catch (error) {
        console.error('Shipping calculation failed:', error);
        return {
          error: {
            reason: 'SHIPPING_ADDRESS_INVALID',
            message: 'Unable to calculate shipping. Please try again.',
            intent: 'SHIPPING_ADDRESS'
          }
        };
      }
      
      const baseAmount = getBaseAmount();
      const tax = calculateTax(address, baseAmount);
      const newTotal = baseAmount + tax + shippingCost;
      
      // Update SDK amount
      pxpSdk.updateAmount(newTotal);
      
      return {
        newTransactionInfo: {
          totalPriceStatus: 'FINAL',
          totalPrice: newTotal.toFixed(2),
          displayItems: [
            { label: 'Subtotal', type: 'LINE_ITEM', price: baseAmount.toFixed(2) },
            { label: 'Shipping', type: 'LINE_ITEM', price: shippingCost.toFixed(2) },
            { label: 'Tax', type: 'TAX', price: tax.toFixed(2) }
          ]
        }
      };
      
    } catch (error) {
      console.error('Payment data changed error:', error);
      return {
        error: {
          reason: 'SHIPPING_ADDRESS_INVALID',
          message: 'An error occurred. Please try again.',
          intent: 'SHIPPING_ADDRESS'
        }
      };
    }
  }
};

Debugging tools and techniques

To get more detailed information about errors, use this comprehensive debugging setup:

// Enable comprehensive logging
window.googlePayDebug = {
  logLevel: 'verbose',
  logPaymentData: false, // Never log actual payment tokens
  logNetworkRequests: true
};

// Debug helper functions
const debugGooglePay = {
  checkEnvironment() {
    console.group('🔍 Google Pay Environment Check');
    console.log('Protocol:', location.protocol);
    console.log('Hostname:', location.hostname);
    console.log('User Agent:', navigator.userAgent);
    console.log('Google Pay API Available:', !!(window.google && window.google.payments));
    console.log('Environment:', pxpSdk.environment);
    console.groupEnd();
  },
  
  logPaymentRequest(request) {
    console.group('📋 Payment Request Configuration');
    console.log('Allowed Payment Methods:', request.allowedPaymentMethods);
    console.log('Transaction Info:', request.transactionInfo);
    console.log('Merchant Info:', request.merchantInfo);
    console.log('Callback Intents:', request.callbackIntents);
    console.groupEnd();
  },
  
  logConfiguration(config) {
    console.group('⚙️ Google Pay Configuration');
    const paymentMethod = config.paymentDataRequest.allowedPaymentMethods[0];
    console.log('Allowed Card Networks:', paymentMethod?.parameters?.allowedCardNetworks);
    console.log('Auth Methods:', paymentMethod?.parameters?.allowedAuthMethods);
    console.log('Billing Address Required:', paymentMethod?.parameters?.billingAddressRequired);
    console.log('Total Price:', config.paymentDataRequest.transactionInfo?.totalPrice);
    console.log('Currency:', config.paymentDataRequest.transactionInfo?.currencyCode);
    console.log('Country Code:', config.paymentDataRequest.transactionInfo?.countryCode);
    // Note: tokenizationSpecification is configured automatically by the SDK
    console.groupEnd();
  },
  
  testReadiness: async function(config) {
    console.group('🧪 Google Pay Readiness Test');
    
    try {
      const paymentsClient = new google.payments.api.PaymentsClient({
        environment: pxpSdk.environment === 'live' ? 'PRODUCTION' : 'TEST'
      });
      
      const isReadyToPayRequest = {
        apiVersion: 2,
        apiVersionMinor: 0,
        allowedPaymentMethods: config.paymentDataRequest.allowedPaymentMethods
      };
      
      const response = await paymentsClient.isReadyToPay(isReadyToPayRequest);
      
      if (response.result) {
        console.log('✅ Google Pay is ready to accept payments');
        console.log('Payment methods available:', response.paymentMethodPresent);
      } else {
        console.warn('⚠️ Google Pay not ready - user may need to add payment methods');
      }
      
    } catch (error) {
      console.error('❌ Readiness test failed:', error);
    }
    
    console.groupEnd();
  }
};

// Use in your implementation
debugGooglePay.checkEnvironment();
debugGooglePay.logConfiguration(googlePayConfig);
await debugGooglePay.testReadiness(googlePayConfig);

Prevention and best practices

Proactive error prevention

// Pre-flight checks before initialising Google Pay
async function performPreflightChecks() {
  const checks = [
    {
      name: 'HTTPS check',
      test: () => location.protocol === 'https:' || location.hostname === 'localhost',
      fix: 'Ensure your site is served over HTTPS'
    },
    {
      name: 'Google Pay API loaded',
      test: () => !!(window.google && window.google.payments && window.google.payments.api),
      fix: 'Ensure Google Pay API script is loaded'
    },
    {
      name: 'Payment methods configured',
      test: () => {
        const pm = googlePayConfig.paymentDataRequest?.allowedPaymentMethods?.[0];
        return pm?.parameters?.allowedCardNetworks?.length > 0;
      },
      fix: 'Configure at least one payment method with allowed card networks'
    },
    {
      name: 'Valid transaction amount',
      test: () => {
        const amount = parseFloat(googlePayConfig.paymentDataRequest.transactionInfo.totalPrice);
        return !isNaN(amount) && amount > 0;
      },
      fix: 'Ensure transaction amount is valid'
    },
    {
      name: 'Browser compatibility',
      test: () => checkBrowserCompatibility(),
      fix: 'Use a supported browser'
    }
  ];
  
  const results = [];
  for (const check of checks) {
    const passed = await check.test();
    results.push({ name: check.name, passed, fix: check.fix });
    
    if (!passed) {
      console.warn(`❌ ${check.name}: ${check.fix}`);
    } else {
      console.log(`✅ ${check.name}`);
    }
  }
  
  return results.every(result => result.passed);
}

function checkBrowserCompatibility() {
  const ua = navigator.userAgent;
  
  // Chrome 61+
  if (/Chrome\/(\d+)/.test(ua)) {
    return parseInt(RegExp.$1) >= 61;
  }
  
  // Safari 12.1+
  if (/Version\/(\d+)/.test(ua) && /Safari/.test(ua)) {
    return parseInt(RegExp.$1) >= 12;
  }
  
  // Firefox 62+
  if (/Firefox\/(\d+)/.test(ua)) {
    return parseInt(RegExp.$1) >= 62;
  }
  
  return false;
}

// Use before initialization
async function initializeGooglePay() {
  const preflightPassed = await performPreflightChecks();
  
  if (preflightPassed) {
    const googlePayButton = pxpSdk.create('google-pay-button', googlePayConfig);
    googlePayButton.mount('google-pay-container');
  } else {
    showFallbackPaymentOptions();
  }
}

Monitoring and alerting

// Error monitoring setup
const errorMonitoring = {
  captureError(error, context) {
    // Send to your error tracking service
    const errorData = {
      message: error.message,
      name: error.name,
      errorCode: error.ErrorCode,
      stack: error.stack,
      context: context,
      userAgent: navigator.userAgent,
      url: location.href,
      timestamp: new Date().toISOString(),
      userId: getCurrentUserId(),
      sessionId: getSessionId()
    };
    
    // Example: Send to Sentry, LogRocket, etc.
    this.sendToErrorService(errorData);
  },
  
  trackGooglePayEvent(eventType, data) {
    // Track Google Pay specific events
    const eventData = {
      type: eventType,
      data: data,
      timestamp: new Date().toISOString(),
      sessionId: getSessionId()
    };
    
    this.sendToAnalytics(eventData);
  }
};

// Integration with Google Pay component
const config = {
  onError: (error) => {
    errorMonitoring.captureError(error, { component: 'GooglePay' });
  },
  
  onPostAuthorisation: (result, paymentData) => {
    const isSuccess = 'merchantTransactionId' in result;
    errorMonitoring.trackGooglePayEvent('payment_completed', {
      success: isSuccess,
      transactionId: result.merchantTransactionId
    });
  }
};