gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
74.8k stars 7.46k forks source link

Figure out how to handle/setup Instagram API token #7879

Closed digitalcraftsman closed 7 months ago

digitalcraftsman commented 3 years ago

What version of Hugo are you using (hugo version)?

$ Hugo 0.76.5

Does this issue reproduce with the latest release?

Yes

How to reproduce?

When using the instagram shortcode with id BWNjjyYFxVx the shortcodes uses this template to construct the url https://api.instagram.com/oembed/?url=https://instagram.com/p/BWNjjyYFxVx. When opening it a notice informs you about the deprecation of the linked API endpoint.

See also #7866.

onedrawingperday commented 3 years ago

As per this document the existing API is deprecated since today October the 24th 2020.

The Facebook Developers documentation points users to a new oEmbed endpoint for Instagram and this document offers instructions about the necessary changes.

As per the doc:

The Instagram oEmbed endpoint requires either an App Access Token (recommended) or Client Access Token.

Basically Facebook has ended free access to the Instagram API.

This affects both the regular and simple Instagram shortcodes.

monsieurnebo commented 3 years ago

So will the built-in GoHugo snippet be updated accordingly? We could imagine an update with this new API, where the API key would be set in the projet config.

onedrawingperday commented 3 years ago

@monsieurnebo

It's more complicated than that.

Facebook now requires registering a website as an app to provide the API keys. A website's calls to the Instagram API will now be tracked and subject to rate limits etc. It is also possible that the Instagram simple shortcode can no longer be refactored in a GDPR compliant way. Website admins will have to gain user consent if they want to serve Instagram content in the EU.

I honestly think that times have changed. Hugo should not enable Facebook's tracking anymore (as well as Google's etc).

Also these built-in shortcodes require maintenance time that could be spent more productively in other areas (hint: remote reesources, pages for data etc.).

ToniTornado commented 3 years ago

Here is my "quick fix"

jasikpark commented 3 years ago

I would say that Hugo should include the information of the api being deprecated, with documentation on how to implement a shortcode yourself, but deprecating the shortcode more generally.

techolik commented 3 years ago

Here is my "quick fix"

  • Go to your Facebook Developer Account (or create one). Go to your app (or create one).
  • Find your App-ID in the top left corner.
  • Go to Dashboard and activate oEmbed.
  • Go to Settings -> Extended -> Security and copy your client token.
  • Create a file layouts/shortcodes/instagram.html in your project.
  • Paste the following content and replace <APPID> and <CLIENTTOKEN> with your credentials:
{{- $pc := .Page.Site.Config.Privacy.Instagram -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
{{ template "_internal/shortcodes/instagram_simple.html" . }}
{{- else -}}
{{ $id := .Get 0 }}
{{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}
{{ with getJSON "https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/" $id "/&hidecaption=" $hideCaption "&access_token=<APPID>|<CLIENTTOKEN>" }}{{ .html | safeHTML }}{{ end }}
{{- end -}}
{{- end -}}

Not sure if it's just me, but getting an error

(#10) To use 'Oembed API', your use of this endpoint must be reviewed and approved by Facebook. To submit this 'Oembed API' feature for review please read our documentation on reviewable features: https://developers.facebook.com/docs/apps/review.

ardianta commented 3 years ago

Here is my "quick fix"

* Go to your Facebook Developer Account (or create one). Go to your app (or create one).

* Find your App-ID in the top left corner.

* Go to `Dashboard` and activate _oEmbed_.

* Go to `Settings -> Extended -> Security` and copy your client token.

* Create a file `layouts/shortcodes/instagram.html` in your project.

* Paste the following content and replace `<APPID>` and `<CLIENTTOKEN>` with your credentials:
{{- $pc := .Page.Site.Config.Privacy.Instagram -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
{{ template "_internal/shortcodes/instagram_simple.html" . }}
{{- else -}}
{{ $id := .Get 0 }}
{{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}
{{ with getJSON "https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/" $id "/&hidecaption=" $hideCaption "&access_token=<APPID>|<CLIENTTOKEN>" }}{{ .html | safeHTML }}{{ end }}
{{- end -}}
{{- end -}}

Did not work for me.

I have another solution:

Instead of embeding it, what if we crawl it. Add the param __a=1 to the instagram URL and you will get JSON of the page.

For example:

https://www.instagram.com/p/CH04mIdlmxg/

Add the __a=1

https://www.instagram.com/p/CH04mIdlmxg/?__a=1

Here what will we get:

Selection_281

Then create custom instagram shortcode: layouts/shortcodes/instagram.html

{{- $pc := .Page.Site.Config.Privacy.Instagram -}}
{{- if not $pc.Disable -}}
    {{- if $pc.Simple -}}
            {{ template "_internal/shortcodes/instagram_simple.html" . }}
    {{- else -}}
            {{ $id := .Get 0 }}
            {{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}
            {{ with getJSON "https://instagram.com/p/" $id "?__a=1" }}
                <figure>
                    <img src="{{ .graphql.shortcode_media.display_url }}" alt="{{ .graphql.shortcode_media.accessibility_caption }}" />
                    {{- if eq $hideCaption "0" -}}
                    {{ $caption := (index .graphql.shortcode_media.edge_media_to_caption.edges 0).node.text }}
                    <figcaption>{{ $caption }}</figcaption>
                    {{ end }}
                </figure>    
            {{ end }}
    {{- end -}}
{{- end -}}
onedrawingperday commented 3 years ago

@ardianta

This is a hack that broke in the past

No way are we going to refactor the Hugo internal shortcodes to use hacks.

monsieurnebo commented 3 years ago

The @ToniTornado 's fix is working fine (thanks!). His code contains some extra features you may not need, so here is a light version of it where Instagram API credentials are stored in the site config (seems cleaner to me):

config.yaml

params:
  instagram:
    appId: "xxxxxx"
    clientToken: "xxxxxx"

layouts/shortcodes/instagram.html

{{- $appId := .Site.Params.Instagram.AppId -}}
{{- $clientToken := .Site.Params.Instagram.ClientToken -}}
{{ $id := .Get 0 }}
{{ with getJSON "https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/" $id "&access_token=" $appId "|" $clientToken }}{{ .html | safeHTML }}{{ end }}
ToniTornado commented 3 years ago

@monsieurnebo, yes, that looks much cleaner! I'm using Hugo only for some side projects. All I did was slightly modifying the original source code to use my id & token.

I believe that most people's issues with my fix are not related to the fix itself but to the corresponding configuration in the Facebook Developer Account. You can debug that by just opening this URL in your browser (replace placeholders with your id & token):

https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/CHc_BmNgRCW&access_token=<YOU_APP_ID>|<YOUR_CLIENT_TOKEN>

You should get the full post as a response in JON format like this:

{
   "version": "1.0",
   "author_name": "kittens_of_world",
   "provider_name": "Instagram",
   "provider_url": "https://www.instagram.com/",
   "type": "rich",
   "width": 658,
   "html": "\u003Cbl.......",
   "...": "...",
}

If you get an error message, you can use that to fix your Facebook setup.

theodore-dream commented 3 years ago

Hello,

Thanks for the hard work here for the fix folks. I just want to note @monsieurnebo that while I love this more fancy/brief method, it didn't work for me. The information from my config file never made it into the shortcode. So my API calls never had properly filled information for the AppID and token.

@ToniTornado your original fix still works though. A secondary issue I hit, just FYI for others - As Toni stated above I did have to debug with that url they provided - and that helped a lot. Going to this page 'https://developers.facebook.com/tools/explorer/' (the instagram graph API explorer) seemed to fix my permissions issue even though I had no idea why.

Just for reference, this is the error I saw when I tried the fancier/briefer method:


Failed to get JSON resource "https://graph.facebook.com/v9.0/instagram_oembed/?url=https://instagram.com/p/CJg-BDPhef9&access_token=|": Failed to retrieve remote file: Bad Request logged 1 error(s)

With this syntax in a .md file for the shortcode: [I share because I think maybe something about the instagram Hugo default shortcode and this custom one may have conflicted?]

{{< instagram CJg-BDPhef9 >}}

Using version:

hugo version Hugo Static Site Generator v0.74.2-48565DE6/extended linux/amd64 BuildDate: 2020-07-17T17:32:27Z

Happy new year

Squirrelq commented 3 years ago

Here is my "quick fix"

  • Go to your Facebook Developer Account (or create one). Go to your app (or create one).
  • Find your App-ID in the top left corner.
  • Go to Dashboard and activate oEmbed.
  • Go to Settings -> Extended -> Security and copy your client token.
  • Create a file layouts/shortcodes/instagram.html in your project.
  • Paste the following content and replace <APPID> and <CLIENTTOKEN> with your credentials:
{{- $pc := .Page.Site.Config.Privacy.Instagram -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
{{ template "_internal/shortcodes/instagram_simple.html" . }}
{{- else -}}
{{ $id := .Get 0 }}
{{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}
{{ with getJSON "https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/" $id "/&hidecaption=" $hideCaption "&access_token=<APPID>|<CLIENTTOKEN>" }}{{ .html | safeHTML }}{{ end }}
{{- end -}}
{{- end -}}

Hi Tony, thanks heaps for the fix, but is there a way to embed the feed so it updates automatically? or can you only embed each post/photo individually? TIA

yikaus commented 3 years ago

Here is my "quick fix"

  • Go to your Facebook Developer Account (or create one). Go to your app (or create one).
  • Find your App-ID in the top left corner.
  • Go to Dashboard and activate oEmbed.
  • Go to Settings -> Extended -> Security and copy your client token.
  • Create a file layouts/shortcodes/instagram.html in your project.
  • Paste the following content and replace <APPID> and <CLIENTTOKEN> with your credentials:
{{- $pc := .Page.Site.Config.Privacy.Instagram -}}
{{- if not $pc.Disable -}}
{{- if $pc.Simple -}}
{{ template "_internal/shortcodes/instagram_simple.html" . }}
{{- else -}}
{{ $id := .Get 0 }}
{{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}
{{ with getJSON "https://graph.facebook.com/v8.0/instagram_oembed/?url=https://instagram.com/p/" $id "/&hidecaption=" $hideCaption "&access_token=<APPID>|<CLIENTTOKEN>" }}{{ .html | safeHTML }}{{ end }}
{{- end -}}
{{- end -}}

Not sure if it's just me, but getting an error

(#10) To use 'Oembed API', your use of this endpoint must be reviewed and approved by Facebook. To submit this 'Oembed API' feature for review please read our documentation on reviewable features: https://developers.facebook.com/docs/apps/review.

The issue you have is tying to embed asset not belongs to you in Facebook or Instagram. Base on explanation https://developers.facebook.com/blog/post/2020/08/04/app-review-improvements-business-developers/

Standard access will be given to your app by default which only allow access assets belong to you. you can request advance access for your app but depends on approval from facebook, or you can create app under assets owner 's account .

bep commented 3 years ago

I will try to fix this in the next Hugo. The recipe above works almost out of the box for me. Some notes: Reusing an old Facebook App doesn't seem to work that well, as they have totally reworked the access setup. So create a new App.

bep commented 3 years ago

Seems like Facebook has done some changes to this ... again, so the APP I created and mentioned in my last comment does not work anymore ... idiots (Facebook, not you).

ToniTornado commented 3 years ago

@bep Same here. I have tried to pass the app review several times now but without success. The forms just don't fit my simple use case.

ToniTornado commented 3 years ago

I finally passed the app review process after some conversation with the Facebook support team. The oEmbed URL field expects a Facebook or Instagram post or profile URL. I was wrongly giving my own website's URL where you could actually see the embedded post. The docs say here https://developers.facebook.com/docs/plugins/oembed/?locale=en_US: "When asked to provide a URL where we can test Oembed Read, include the URL of a page, post, or video from our official Facebook or Instagram pages, or the pages themselves."

By "our" they seem to mean "your" in this case. So yes, you really give some Instagram or Facebook link there! And there is one KNOWN bug: The URL will be converted to lowercase when you save the form so that when it contains a case-sensitive Instagram-ID it will no longer work!

As a workaround I just posted my Intagram profile URL that did not contain any capital letters.

nipa-it commented 3 years ago

Hi all, as from 25 Jun none of the Apps category (business, none, customer etc.) seems to allow Oembed plugin.

"None" category that looks the one with more plugins available doesn't offer such a possibility...

Anyone has find out how to solve?

cathrinew commented 3 years ago

In case anyone else comes looking for a workaround until this issue is resolved:

My solution was to create a custom shortcode with the native embed code found through the Embed Button. It doesn't use an API, and doesn't need an app. It's not the most elegant or future-proof solution, but it works like a charm for now and I can keep using the default:

{{< instagram BWNjjyYFxVx >}}

(If you embed photos from multiple users, you have to customize the shortcode with a few additional parameters to pass in their name and username.)

ardianta commented 3 years ago

@cathrinew I was use endpoint of the embed button, and it works.

Here my custom shortcode:

{{ $id := .Get 0 }}
{{ $hideCaption := cond (eq (.Get 1) "hidecaption") "1" "0" }}

{{ if not .Site.IsServer }}
{{ with getJSON "https://api.instagram.com/oembed/?url=https://www.instagram.com/p/" $id "/&hidecaption=" $hideCaption }}
    {{ .html | safeHTML }}
{{ end }}
{{ else }}
<style>
  .instagram-embed-placeholder {
    display: flex; 
    align-items: center; 
    justify-content: center;
    gap: .5em; 
    border: 2px dashed silver; 
    height: 360px; 
    margin: 2em 0; 
    border-radius: 8px;
  }
</style>
<div class='instagram-embed-placeholder'>
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-instagram" viewBox="0 0 16 16">
    <path d="M8 0C5.829 0 5.556.01 4.703.048 3.85.088 3.269.222 2.76.42a3.917 3.917 0 0 0-1.417.923A3.927 3.927 0 0 0 .42 2.76C.222 3.268.087 3.85.048 4.7.01 5.555 0 5.827 0 8.001c0 2.172.01 2.444.048 3.297.04.852.174 1.433.372 1.942.205.526.478.972.923 1.417.444.445.89.719 1.416.923.51.198 1.09.333 1.942.372C5.555 15.99 5.827 16 8 16s2.444-.01 3.298-.048c.851-.04 1.434-.174 1.943-.372a3.916 3.916 0 0 0 1.416-.923c.445-.445.718-.891.923-1.417.197-.509.332-1.09.372-1.942C15.99 10.445 16 10.173 16 8s-.01-2.445-.048-3.299c-.04-.851-.175-1.433-.372-1.941a3.926 3.926 0 0 0-.923-1.417A3.911 3.911 0 0 0 13.24.42c-.51-.198-1.092-.333-1.943-.372C10.443.01 10.172 0 7.998 0h.003zm-.717 1.442h.718c2.136 0 2.389.007 3.232.046.78.035 1.204.166 1.486.275.373.145.64.319.92.599.28.28.453.546.598.92.11.281.24.705.275 1.485.039.843.047 1.096.047 3.231s-.008 2.389-.047 3.232c-.035.78-.166 1.203-.275 1.485a2.47 2.47 0 0 1-.599.919c-.28.28-.546.453-.92.598-.28.11-.704.24-1.485.276-.843.038-1.096.047-3.232.047s-2.39-.009-3.233-.047c-.78-.036-1.203-.166-1.485-.276a2.478 2.478 0 0 1-.92-.598 2.48 2.48 0 0 1-.6-.92c-.109-.281-.24-.705-.275-1.485-.038-.843-.046-1.096-.046-3.233 0-2.136.008-2.388.046-3.231.036-.78.166-1.204.276-1.486.145-.373.319-.64.599-.92.28-.28.546-.453.92-.598.282-.11.705-.24 1.485-.276.738-.034 1.024-.044 2.515-.045v.002zm4.988 1.328a.96.96 0 1 0 0 1.92.96.96 0 0 0 0-1.92zm-4.27 1.122a4.109 4.109 0 1 0 0 8.217 4.109 4.109 0 0 0 0-8.217zm0 1.441a2.667 2.667 0 1 1 0 5.334 2.667 2.667 0 0 1 0-5.334z"/>
  </svg>
    <a href='https://www.instagram.com/p/{{ $id }}/' target="_blank" rel="noopener">
      Instagram Embed: {{ $id }}
    </a>
</div>
{{ end }}

The API endpoint was back to normal. lol :rofl: But I don't know, how long it will be available for public.

tphummel commented 3 years ago

One workaround I'm exploring is to export all of my images from IG, close my IG account, and host the images directly in my Hugo site.

jasikpark commented 3 years ago

One workaround I'm exploring is to export all of my images from IG, close my IG account, and host the images directly in my Hugo site.

doable via a data download request! https://www.cnet.com/tech/mobile/how-to-download-all-your-instagram-data/

tphummel commented 3 years ago

For the record, I did an Instagram account export and replaced my Instagram embeds with self hosted images. I only had a single post with embeds to replace so effort was manageable.

https://github.com/tphummel/blog/commit/d999c9dbc7dfd1d64159b2ab4ae4f706e2860f39

jasikpark commented 2 years ago

Alternatively, what if there was support for importing external shortcodes into Hugo, so this both can be moved out of core & is still very accessible to where people don't have to write their own shortcode to support it! I haven't taken a look at theming in Hugo in a while... would go modules work for that?

jasikpark commented 2 years ago

You can! https://gohugo.io/hugo-modules/use-modules/ :D perhaps gohugio/social-shortcodes or a community version?

ardianta commented 2 years ago

Cant you just use something like this?

https://www.instagram.com/p/CRoxgPrDjgw/embed/

This is a good alternative for iframe lazyloading, thank you.

basnijholt commented 1 year ago

Note that there is a solution here by @jhvanderschee.

I have tried all the other solutions above without avail. The solution I linked works well for me at https://www.nijho.lt/

bep commented 7 months ago

Closing this as "out of scope" or: Too hard.

jhvanderschee commented 7 months ago

Note that there is a solution here by @jhvanderschee.

I have tried all the other solutions above without avail. The solution I linked works well for me at https://www.nijho.lt/

The PPI service is no longer active due to the ongoing 'sabotage' from Facebook. Here is a good alternative that is easy to implement in your Hugo website: https://www.usecue.com/blog/free-instagram-widget/.

github-actions[bot] commented 6 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.