Posts tagged with javascript

I uploaded a photo via WhatsApp, which can be accessed via:

https://graph.facebook.com/v19.0/{imageId} 

Requesting this API returns the URL of the image:

{     "url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid={imageId}&ext={ext}&hash={hash}",     "mime_type": "image/jpeg",     "sha256": "fd9d5ac5bb84b8a0b7a3402c3a99ed9ff3e9fadb4fa567cd101eaf4923d2b375",     "file_size": 667836,     "id": "{imageId}",     "messaging_product": "whatsapp" } 

Then, accessing this URL by Postman successfully returns the image that I uploaded.

However, when I use Nodejs, it returns something that I cannot convert to an image to be displayed on browsers.

const url = (   await axios.get("https://graph.facebook.com/v19.0/{imageId}", {     headers: {       Authorization: `Bearer ${process.env.WHATSAPP_API_KEY}`,     },   }) ).data.url; const image = Buffer.from(   (     await axios.get(url, {       method: "GET",       headers: {         Authorization: `Bearer ${process.env.WHATSAPP_API_KEY}`,       },     })   ).data ).toString("base64"); console.log(image); // 77+977+977+977+9ABBKRklGAAEBAQBgAGAAAO+... 

This prints some base64-encoded string, but when I test it https://base64.guru/converter/decode/image here, it tells that the string represents an application/octet-stream data. Therefore, I cannot display the image in my Remix code.

<img src={`data:image/jpeg;base64,${image}`} /> // not working 

How can I appropriately retrieve the image as base64 from the API?

I create a mobile app who show local crickets score card by programming in react native expo cli. https://play.google.com/store/apps/details?id=com.rafiullahkh.lcsa Now i want to update the app and want to integrate a score card in facebook/youtube live stream. If possible then gave me some hints.

I search a lot but does not find any documentation.

I'm encountering an issue with Facebook's Graph API where it inconsistently scrapes Open Graph (OG) meta tags between different language versions of my website, which is built using Next.js version 14 with an architecture using page router. Specifically, the French version of my URLs (manage by a context) consistently returns all expected OG meta data (title, description, image), whereas the regular English version sometimes only returns minimal data (type, updated_time), missing critical tags like title, description, and image.

Here are the key details:

Platform: Next.js version 14 with dynamic content rendering based on user language preferences, which is managed by a context.

Behavior: When using Facebook's Graph API Explorer or the Sharing Debugger, the French URL (e.g., https://wiseduckdev.vercel.app/fr/gpts/framework) always successfully returns full meta tag information. However, the equivalent English URL (e.g., https://wiseduckdev.vercel.app/gpts/framework) often only returns partial data.

Meta Tags: Both versions use identical setups for Open Graph meta tags, confirmed via direct source inspection and tools like SEO Meta in 1 Click.

 <meta property="og:type" content="website" />           <meta property="og:title" content={pageData.category.og_title} />           <meta             property="og:description"             content={pageData.category.og_description}           />           <meta             property="og:url"             content={               activeLanguage === "FR"                 ? `https://${siteUrl}/fr/gpts/${pageData.category.category}`                 : `https://${siteUrl}/gpts/${pageData.category.category}`             }           />           <meta             property="og:image"             content={`https://${siteUrl}${pageData.category.og_image}`}           />           <meta             property="og:locale"             content={translation.og_locale[activeLanguage]}           /> 

Caching: I've purged both server and Facebook caches and forced re-scraping using Facebook's tools, which sometimes resolves the issue temporarily for English URLs but doesn't provide a consistent fix.

I'm looking for insights or suggestions on why this discrepancy might be occurring and how to ensure consistent meta tag scraping by Facebook across all language versions of my site.

Actions Taken to Resolve the Issue:

  • Meta Tag Verification: Confirmed that both the English and French versions of the site have correctly implemented Open Graph (OG) meta tags (og:title, og:description, og:image) using direct source inspection and SEO Meta in 1 Click.
  • Caching Management: Purged server and Facebook caches to ensure fresh data is being fetched and used the Facebook Sharing Debugger to force re-scraping of the URLs.
  • Server Response Checks: Used curl to simulate Facebook’s scraper requests, verifying that the server sends the correct metadata and appropriate HTTP responses.
  • Dynamic Content Handling: Ensured that metadata is dynamically generated based on user language settings and is properly rendered server-side in both language versions.
  • API Utilization: Utilized Facebook’s Graph API Explorer to manually fetch data for both language versions to check the responses and confirm that the issue persists despite correct setup.

Expectations and Goals:

  • Consistent Meta Tag Scraping: Ensure that Facebook’s scraper consistently retrieves all relevant OG meta tags across all language versions of the site, not just the French version.
  • Understanding Root Cause: Gain insights into why the English version sometimes only returns minimal data (type, updated_time) despite identical setups.
  • Reliable Resolution: Find a reliable solution or workaround that ensures all versions of the site are equally optimized for social media sharing, without needing to manually trigger re-scrapes.

I have the following code executing when a user logs in to facebook:

FB.Event.subscribe('auth.authResponseChange', checkLoginState); 

Here is the code to analayse:

    function checkLoginState(response) {         if (response.authResponse) {             // User is signed-in Facebook.             const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {                 unsubscribe();                 // Check if we are already signed-in Firebase with the correct user.                 if (!isUserEqual(response.authResponse, firebaseUser)) {                     // Build Firebase credential with the Facebook auth token.                     const credential = FacebookAuthProvider.credential(                         response.authResponse.accessToken);                     // Sign in with the credential from the Facebook user.                     let x = signInWithCredential(auth, credential)                         .catch((error) => {                             // Handle Errors here.                             const errorCode = error.code;                             const errorMessage = error.message;                             // The email of the user's account used.                             const email = error.customData.email;                             // The AuthCredential type that was used.                             const credential = FacebookAuthProvider.credentialFromError(error);                             alert("Login failed. Please try again.");                         });                     x.then((userCredential) => {                         // Signed in                         const user = userCredential.user;                         // login(response.authResponse.accessToken, firebasetoken???);                     });                 } else {                     // User is already signed-in Firebase with the correct user.                     console.log(response);                     // login(response.authResponse.accessToken, firebasetoken???);                 }             });         } else {             // User is signed-out of Facebook.             signOut(auth);         }     } 

I'm unsure how to pass the FIREBASE login token to verify in the backend (with kreait):

        $auth = (new Factory)             ->withServiceAccount($_ENV["PATH"].$_ENV['config']['storage']['firebase']['firebase']['file'] ?? 'firebase-service-account.json')             ->createAuth();         // verify token         $verifiedIdToken = $auth->verifyIdToken($token);         $uid = $verifiedIdToken->getClaim('sub'); // throws an InvalidToken when invalid 

Kreait docs: https://github.com/kreait/firebase-php

Any help is appreciated.

I've tried with this documentation authenticate and with this REST to send the conversion over REST API due to missing Typescript/Javascript-Client-Bib.

I am already failing at the authentication. I hope, if the authentication is working, the click conversion will be send. For the case I am guessing wrong, I extended the question. I hope the question is not to big. Blame me if I am wrong.

This is my error:

My setup Regarding to the documentation I have a google ads account with a developer token. This token will be used, when I send the click conversion, as you can see here. The token has nothing to do with the authentication of the service account. Therefore I have a service account on the Google Cloud Project, which also has the Google Ads Api enabled.

I also added to the workspace domain to the domain wide delegation the client id of the service account with the scope https://www.googleapis.com/auth/adwords This created in the category APIs & Services also an OAuth 2.0 Client IDs The clientIds are fitting as well.

Just in case I also added an OAuth consent screen with the scope https://www.googleapis.com/auth/adwords with the Testing status and external. But I don't think I will need this with a service account.

The service account itself has no further related rights. The documentation don't give me the info, that the service account need further rights. My thoughts: I added the client id to the domain wide delegation, this should be enough. I hope I am wrong here.

Now everything should be set up. I hope I didn't miss a step.

My guess: Either I am missing some rights. Or I missunderstand the refresh token in the function authenticateToGoogleAdsManager. I create a signed JWT. Google says here, I need a refresh token. But the authentication via await fetch('https://oauth2.googleapis.com/token' just gives me an access token. So I thought I just need a jwt here.

This is the way I am executing my code (in a testcase. Service Account JSON and clickConversion are given.)

 // First I create a signed jwt     const jwt = generateJsonWebTokenForServiceAccount(       serviceAccount,       ['https://www.googleapis.com/auth/adwords'],       'googleads'     )     // Then I use the signed jwt to authenticate to Google Ads Manager     const authenticationResult = await authenticateToGoogleAdsManager(       serviceAccount.client_id,       serviceAccount.private_key,       jwt     )     console.log(authenticationResult)     // Then I use the access token to send a click conversion to Google Ads Manager     const test = await sendClickConversionToGoogleAdsManager(       CUSTOMERID,       clickConversion,       accessToken.access_token,       'DEV-TOKEN'     ) 

Here are my functions:

/**  * Generates a JSON Web Token (JWT) for a service account.  *  * @param serviceAccount - The service account object containing the client email and private key.  * @param scopes - An array of scopes for which the token will be authorized.  * @param serviceName - The name of the service for which the token will be authorized. Default is 'oauth2'.  * @param expirationTimeInSeconds - The expiration time of the token in seconds. Default is 3600 seconds (1 hour).  * @returns The generated JSON Web Token.  */ export function generateJsonWebTokenForServiceAccount(serviceAccount: ServiceAccount,   scopes: string[],   serviceName: string = 'oauth2',   expirationTimeInSeconds = 3600) {   const aud =     serviceName === 'oauth2' ? 'https://oauth2.googleapis.com/token' : `https://${serviceName}.googleapis.com/`   const currentTimestamp = Math.floor(Date.now() / 1000)   const expirationTimestamp = currentTimestamp + expirationTimeInSeconds   const payload = {     iss: serviceAccount.client_email,     sub: serviceAccount.client_email,     scope: scopes.join(' '),     aud: aud,     exp: expirationTimestamp,     iat: currentTimestamp   }   const options: SignOptions = {     algorithm: 'RS256'   }   return jwt.sign(payload, serviceAccount.private_key, options) } /**  * Authenticates to Google Ads Manager using the provided credentials.  * @param clientId The client ID for authentication.  * @param clientSecret The client secret for authentication.  * @param refreshToken The refresh token for authentication.  * @returns A promise that resolves to the access token.  */ export async function authenticateToGoogleAdsManager(clientId: string,   clientSecret: string,   refreshToken: string): Promise<string> {   const url = 'https://www.googleapis.com/oauth2/v3/token'   const body = {     client_id: clientId,     client_secret: clientSecret,     refresh_token: refreshToken,     grant_type: 'refresh_token'   }   const response = await fetch(url, {     method: 'POST',     body: JSON.stringify(body)   })   const data = await response.json()   return data.access_token } /**  * Sends a click conversion to Google Ads Manager.  *   * @param customerId - The ID of the customer.  * @param clickConversion - The click conversion data.  * @param accessToken - The access token for authentication.  * @param developerToken - The developer token for authentication.  * @param options - Optional API options.  * @returns A promise that resolves to void.  */ export async function sendClickConversionToGoogleAdsManager(customerId: number,   clickConversion: ClickConversion,   accessToken: string,   developerToken: string,   options?: ApiOptions): Promise<void> {   const url = `https://googleads.googleapis.com/v15/customers/${customerId}:uploadClickConversions`   if (!options) {     options = {       partialFailure: false,       validateOnly: false,       debugEnabled: false,       jobId: 0     }   }   const response = await fetch(url, {     method: 'POST',     headers: {       'Content-Type': 'application/json',       Authorization: `Bearer ${accessToken}`,       'developer-token': developerToken     },     body: JSON.stringify({       conversions: [clickConversion],       partialFailure: options.partialFailure,       validateOnly: options.validateOnly,       debugEnabled: options.debugEnabled,       jobId: options.jobId     })   })   const data = await response.json()   return data }