Skip to content

Popup Services

The popup services provide utilities for opening popup windows, typically used for OAuth authentication flows or external integrations that require user interaction in a separate window.


FunctionDescription
openPopUp(url)Opens a popup and extracts state parameter from redirect URL
openPopUpBlank(url)Opens a popup and waits for it to return to same origin

Opens a centered popup window and monitors for OAuth-style redirects. When the popup navigates to a URL containing a state parameter, it extracts and returns the decoded state.

async function openPopUp(url: string): Promise<{
type: 'integration';
data: any;
}>
import { openPopUp } from '@ion-components/packages/services/popup.services';
async function connectShopify() {
try {
const result = await openPopUp('https://api.example.com/oauth/shopify/start');
// result.data contains the decoded state from OAuth callback
console.log('Integration data:', result.data);
// Typically contains: shop domain, access token, etc.
saveIntegration(result.data);
} catch (error) {
console.error('OAuth failed:', error);
}
}
  1. Opens a centered popup window (550x660 pixels)
  2. Monitors the popup URL every 500ms
  3. When the URL contains a state query parameter, it:
    • Decodes the base64-encoded state
    • Parses it as JSON
    • Closes the popup
    • Returns the data

Opens a popup and waits for it to return to the same origin (typically after an external process completes).

async function openPopUpBlank(url: string): Promise<void>
import { openPopUpBlank } from '@ion-components/packages/services/popup.services';
async function handleExternalAuth() {
// Open external authentication page
await openPopUpBlank('https://external-service.com/auth');
// Control returns here after popup closes or returns to same origin
console.log('External auth completed');
// Refresh data that might have been updated externally
await refreshIntegrations();
}
  1. Opens a centered popup window (550x660 pixels)
  2. Monitors the popup every 500ms
  3. Resolves when:
    • The popup is closed by the user, OR
    • The popup navigates to the same origin as the parent window

import { openPopUp } from '@ion-components/packages/services/popup.services';
// Component for managing integrations
const integrations = ref([]);
async function addShopifyIntegration() {
try {
// 1. Start OAuth flow - opens Shopify login
const result = await openPopUp('/oauth/shopify/authorize');
// 2. result.data contains the shop info after OAuth completes
const { shop, accessToken, scope } = result.data;
// 3. Save the integration
await apiService.create({
provider: 'shopify',
shop,
accessToken,
scope,
});
// 4. Refresh list
await loadIntegrations();
showSuccess('Shopify connected successfully!');
} catch (error) {
if (error.message === 'Popup closed by user') {
// User cancelled - no action needed
return;
}
showError('Failed to connect Shopify: ' + error.message);
}
}
async function addGoogleIntegration() {
try {
const result = await openPopUp('/oauth/google/authorize');
const { email, refreshToken, accessToken } = result.data;
await apiService.create({
provider: 'google',
email,
refreshToken,
accessToken,
});
await loadIntegrations();
showSuccess('Google connected successfully!');
} catch (error) {
handleOAuthError(error);
}
}

Your backend OAuth flow should:

  1. Initiate the OAuth process
  2. Handle the callback from the OAuth provider
  3. Encode the result in a state parameter
  4. Redirect to a page that includes this state in the URL
public function handleCallback(Request $request)
{
// ... OAuth token exchange logic ...
$state = base64_encode(json_encode([
'shop' => $shop->name,
'accessToken' => $accessToken,
'scope' => $scope,
]));
return redirect('/oauth/complete?state=' . $state);
}
/oauth/complete
<!DOCTYPE html>
<html>
<head>
<title>Connection Complete</title>
</head>
<body>
<p>Connection successful! This window will close automatically.</p>
</body>
</html>

Both functions can throw errors in these scenarios:

ScenarioError
Popup blockedBrowser blocked the popup
User closes popupUser cancelled the flow
Invalid stateCannot parse the returned state
Network errorOAuth provider unreachable
try {
await openPopUp(authUrl);
} catch (error) {
if (error.message.includes('blocked')) {
showError('Please allow popups for this site');
} else if (error.message.includes('closed')) {
// User cancelled - silent failure
} else {
showError('Authentication failed. Please try again.');
}
}