garmeeh / next-seo

Next SEO is a plug in that makes managing your SEO easier in Next.js projects.
MIT License
7.72k stars 402 forks source link

OG Image url encoding results in wrong url #954

Open rhythmbhiwani opened 2 years ago

rhythmbhiwani commented 2 years ago

Describe the bug A clear and concise description of what the bug is. I am using the vercel og-image service to serve og images for my app. The url generates dynamic og images using the supplied query parameters which are supplied using the & symbol in url. But next-seo encodes the url resulting in & which breaks the url and does not give expected result

Reproduction For issues to be triaged in a timely manner please provide a Codesandbox/Github of the issue in it's simplest reproduction.

Original Image URL: https://og-image.vercel.app/**Hello**%20World.png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fvercel-triangle-black.svg

Encoded Image URL generated by next-seo : https://og-image.vercel.app/**Hello**%20World.png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fvercel-triangle-black.svg

Expected behavior A clear and concise description of what you expected to happen. Is there a option so we can skip encoding the url, or any other workaround for it.

Additional context Add any other context about the problem here.

buraste commented 2 years ago

Same as me. next-seo encode urls so If has ampersand, It breaks the urls.

JamesSingleton commented 2 years ago

Yeah I just ran into this where I have an & in an Article title as well as the URL for images and it is resulting in the &

JamesSingleton commented 2 years ago

@garmeeh I know you had mentioned that this might be an issue with react. However, I am able to do

<Head>
  <script
    id="app-ld-json"
    type="application/ld+json"
    dangerouslySetInnerHTML={{
      __html: JSON.stringify(content),
    }}
  />
</Head>

where content has URLs like https://cdn.sanity.io/images/8pbt9f8w/production/4970237430aef6b6d4fe9d165d32d46ef2492bb7-1408x792.jpg?fit=min&auto=format and doing dangerouslySetInnerHTML doesn't turn that & into an &amp;. The issue isn't React but the fact that toJson is escaping those characters: https://github.com/garmeeh/next-seo/blob/master/src/utils/toJson.tsx#L32

ianwensink commented 2 years ago

Did anyone find a workaround for this? Encoding the URL before providing it to next-seo solves the issue, but I'm not sure if you can have encoded url's in an og:image tag.

JamesSingleton commented 2 years ago

@ianwensink I ended up just rolling my own solution

ianwensink commented 2 years ago

@JamesSingleton ah! Which was? Just not using the og solution of next-seo?

JamesSingleton commented 2 years ago

@ianwensink yup! So I just ended up doing

<Head>
  <script
    id="app-ld-json"
    type="application/ld+json"
    dangerouslySetInnerHTML={{
      __html: JSON.stringify(content),
    }}
  />
</Head>

And passed my own content to JSON.stringify()... I mean if you are sanitizing/escaping stuff then it isn't so dangerous 😅 plus next-seo doesn't have/allow everything that is supported by ld+json so I ended up rolling my own so I can get the full benefit of ld+json. In my example, the content passed to JSON.stringify() looks like the following

 const content = {
    '@context': 'http://schema.org',
    '@graph': [
      Organization,
      WebSite,
      {
        '@type': 'WebPage',
        '@id': `${SITE_URL}/#webpage`,
        url: SITE_URL,
        name: 'Redshirt Sports',
        isPartOf: {
          '@id': `${SITE_URL}/#website`,
        },
        about: {
          '@id': `${SITE_URL}/#organization`,
        },
        dateModified: mainArticle._updatedAt,
        description:
          'Redshirt Sports brings you the College Football Championship Subdivision (FCS) news, standings, rumors, and more.',
        breadcrumb: {
          '@id': `${SITE_URL}/#breadcrumb`,
        },
        inLanguage: 'en-US',
        potentialAction: [
          {
            '@type': 'ReadAction',
            target: [SITE_URL],
          },
        ],
      },
      {
        '@type': 'BreadcrumbList',
        '@id': `${SITE_URL}/#breadcrumb`,
        name: 'Home Breadcrumbs',
        itemListElement: [
          {
            '@type': 'ListItem',
            position: 1,
            name: 'Home',
            item: SITE_URL,
          },
        ],
      },
    ],
  }
iners-max commented 1 year ago

Hi, do you have any plan to fix the issue? looks like setting URLs in tags with '&' does not work.

CesarBenavides777 commented 1 year ago

@iners-max @rhythmbhiwani

I managed to do something like this and it works on next-seo:

const url = process.env.NODE_ENV === "production"
    ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
    : "http://localhost:3000";

    const og = new URL(`${url}/api/og/?title=${title}${
      metaDesc ? `&description=${metaDesc}` : ""
    }`)

Then in openGraph Settings:

openGraph={{
        url: canonical ?? ``,
        title: opengraphTitle ?? ``,
        description: metaDesc ?? ``,
        siteName: opengraphSiteName ?? ``,
        images: [
          {
            url: og.href,
            width: 1200,
            height: 627,
            alt: metaDesc ? metaDesc : ``,
          },
        ],
      }}
lazarok09 commented 1 year ago

Same issue here

Kolby-Udacity commented 1 year ago

Has anyone found a good workaround to this problem?

lenardchristopher commented 4 months ago

Still an issue here.

My workaround is to base64 encode all the params so the url is only being passed a single query param thereby avoiding use of &/;amp.

export const buildUrlWithBase64EncodedParamsAsSingleParam = (baseUrl, params): string => {
  const url = new URL(baseUrl, process.env.NEXT_PUBLIC_API_URL);
  var b64param = btoa(JSON.stringify(params));
  return `${url.toString()}?params=${b64param}`;
};