exports.googleAdsAccountCallback = asyncHandler(async (req, res) => {
try {
const { code, state } = req.query;
const { userId, organizationId } = JSON.parse(state);
const { tokens } = await oAuth2Client.getToken(code);
oAuth2Client.setCredentials(tokens);
const oauth2 = google.oauth2({ version: 'v2', auth: oAuth2Client });
const userInfoResponse = await oauth2.userinfo.get();
const { id: googleId, email } = userInfoResponse.data;
const googleAdsClient = new GoogleAdsApi({
client_id: '#',
client_secret: '#',
developer_token: '#'
});
let accessibleCustomers;
try {
accessibleCustomers = await googleAdsClient.listAccessibleCustomers({
refresh_token: tokens.refresh_token
});
console.log('Accessible customers:', accessibleCustomers);
} catch (error) {
console.error('Error retrieving accessible customers:', error);
}
let adsManager = await GoogleAdsManager.findOne({
userId: mongoose.Types.ObjectId(userId),
organizationId: organizationId ? mongoose.Types.ObjectId(organizationId) : null,
googleId
});
if (adsManager) {
adsManager.accessToken = tokens.access_token;
adsManager.refreshToken = tokens.refresh_token || adsManager.refreshToken;
adsManager.tokenExpiry = new Date(tokens.expiry_date);
adsManager.isActive = true;
adsManager.lastSyncedAt = new Date();
} else {
const data = {
userId: mongoose.Types.ObjectId(userId),
organizationId: organizationId ? mongoose.Types.ObjectId(organizationId) : null,
googleId,
email,
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
tokenExpiry: new Date(tokens.expiry_date)
};
adsManager = new GoogleAdsManager(data);
}
await adsManager.save();
const script = `
<script>
window.opener.postMessage({
status: 'success',
message: 'Google Ads account connected successfully',
data: {
googleId: '${googleId}',
email: '${email}'
}
}, 'http://localhost:3000');
window.close();
</script>
`;
res.send(script);
} catch (error) {
console.error('Error in callback:', error);
const script = `
<script>
window.opener.postMessage({
status: 'error',
message: 'Error connecting Google Ads account'
}, 'http://localhost:3000');
window.close();
</script>
`;
res.send(script);
}
});
Error:
Error retrieving accessible customers: Error: 2 UNKNOWN: Getting metadata from plugin failed with error: invalid_request
at callErrorFromStatus (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\call.js:31:19)
at Object.onReceiveStatus (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\client.js:193:76)
at Object.onReceiveStatus (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:360:141)
at Object.onReceiveStatus (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:323:181)
at D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\resolving-call.js:129:78
at processTicksAndRejections (node:internal/process/task_queues:78:11)
for call at
at ServiceClientImpl.makeUnaryRequest (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\client.js:161:32)
at ServiceClientImpl.<anonymous> (D:\NLM\mymanager\server\node_modules\@grpc\grpc-js\build\src\make-client.js:105:19)
at D:\NLM\mymanager\server\node_modules\google-ads-node\build\src\v17\customer_service_client.js:370:29
at D:\NLM\mymanager\server\node_modules\google-gax\build\src\normalCalls\timeout.js:44:16
at repeat (D:\NLM\mymanager\server\node_modules\google-gax\build\src\normalCalls\retries.js:82:25)
at D:\NLM\mymanager\server\node_modules\google-gax\build\src\normalCalls\retries.js:125:13
at OngoingCallPromise.call (D:\NLM\mymanager\server\node_modules\google-gax\build\src\call.js:67:27)
at NormalApiCaller.call (D:\NLM\mymanager\server\node_modules\google-gax\build\src\normalCalls\normalApiCaller.js:34:19)
at D:\NLM\mymanager\server\node_modules\google-gax\build\src\createApiCall.js:112:30
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 2,
details: 'Getting metadata from plugin failed with error: invalid_request',
metadata: Metadata { internalRepr: Map(0) {}, options: {} },
note: 'Exception occurred in retry method that was not classified as transient'
}