├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── index.html ├── jquery.instagramFeed.js ├── jquery.instagramFeed.min.js ├── package.json └── test.html /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-vendored -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.paypal.me/JavierSL'] 13 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Actions CI Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - dev 8 | pull_request: 9 | branches: 10 | - master 11 | - dev 12 | 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | node-version: [8.x, 10.x, 12.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v1 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - name: npm install, build, and test 27 | run: | 28 | npm install 29 | npm test 30 | env: 31 | CI: true 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please **first discuss the change you wish to make via issue**, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | ## Pull Request Process 7 | 8 | 1. Install all the dependencies using `npm install` 9 | 2. Make your changes and test them. Note that depending on your changes you may also have to modify existing tests or create new ones. 10 | 3. **Run the tests** using `npm run test` 11 | 4. **Build** the minified version using `npm run build` 12 | 5. **Update the docs** (index.html) with the changes. If it is a new feature ensure to include it in the first example. 13 | 6. **Increase the version numbers in every file** where the version number is present to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 14 | 15 | ## Optional 16 | 17 | Consider making your changes also in [InstagramFeed](https://github.com/jsanahuja/InstagramFeed). -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | babel: { 4 | options: { 5 | sourceMap: false, 6 | comments: false, 7 | sourceType: "unambiguous", 8 | presets: ['@babel/preset-env', 'minify'] 9 | }, 10 | dist: { 11 | files: { 12 | 'jquery.instagramFeed.min.js': ['jquery.instagramFeed.js'] 13 | } 14 | } 15 | }, 16 | qunit: { 17 | files: ['test.html'], 18 | options: { 19 | puppeteer: { 20 | ignoreDefaultArgs: true, 21 | args: [ 22 | "--headless", 23 | "--disable-web-security", 24 | "--allow-file-access-from-files" 25 | ] 26 | }, 27 | timeout: 10000 28 | }, 29 | } 30 | }); 31 | grunt.loadNpmTasks('grunt-contrib-qunit'); 32 | grunt.registerTask('test', 'qunit'); 33 | 34 | grunt.loadNpmTasks('grunt-babel'); 35 | grunt.registerTask('build', ['babel']); 36 | }; 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Javier Sanahuja 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ This repository has been archived ⚠️ 2 | 3 | The focus of this repository was to provide an easy and ready to use plugin to display an Instagram Feed but since latest Instagram changes, this no longer makes sense. Please, move to an official API based plugin. 4 | 5 | If you feel this repo should not be archived, please reach out and let us know. Archiving can always be reversed if needed. 6 | 7 | # jquery.instagramFeed [](https://travis-ci.com/jsanahuja/jquery.instagramFeed) 8 | Instagram Feed without using the instagram API 9 | 10 | Try [InstagramFeed](https://github.com/jsanahuja/InstagramFeed), the same without jQuery. 11 | 12 | ## Documentation 13 | 14 | [Full documentation and examples here](https://www.sowecms.com/demos/jquery.instagramFeed/index.html "documentation") 15 | 16 | ## Contributing 17 | 18 | Read and follow the [CONTRIBUTING.md](./CONTRIBUTING.md) before sending any pull request. 19 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |Instagram Feed without access token. We like Instagram but hate his API
96 | 100 || Attribute | 153 |Type | 154 |Default | 155 |Description | 156 |
|---|---|---|---|
161 | username162 | Required / Optional 163 | |
164 | String | 165 |null |
166 | Instagram username from where to retrieve the feed. Required if tag, location and user_id are not defined. | 167 |
170 | tag171 | Required / Optional 172 | |
173 | String | 174 |null |
175 | Instagram tag from where to retrieve the feed. Required if username, location and user_id are not defined. | 176 |
179 | location180 | Required / Optional 181 | |
182 | String | 183 |null |
184 | Instagram location '{id}/{slug}' from where to retrieve the feed. Required if username, tag and user_id are not defined. | 185 |
188 | user_id189 | Required / Optional 190 | |
191 | String | 192 |null |
193 | Instagram user ID for GraphQL API. Required if username, tag and location are not defined. Not recommended as Instagram is CORS restricted again | 194 |
197 | container198 | Required / Optional 199 | |
200 | String | 201 |null |
202 | Selector where to place the feed. Required if callback is not defined. | 203 |
206 | callback207 | Required / Optional 208 | |
209 | function(data) | 210 |null |
211 | Callback function with all the data fetched from instagram. Required if container is not defined. | 212 |
215 | display_profile
216 | |
217 | Boolean | 218 |true |
219 | Enables displaying the profile. Not compatible when loading from GraphQL API with user_id | 220 |
223 | display_biography
224 | |
225 | Boolean | 226 |true |
227 | Enables displaying the biography. Not compatible when loading a tag, location or user_id | 228 |
231 | display_gallery
232 | |
233 | Boolean | 234 |true |
235 | Enables displaying the gallery | 236 |
239 | display_captions
240 | |
241 | Boolean | 242 |false |
243 | Enables displaying captions for each post as overlay on hover | 244 |
247 | display_igtv
248 | |
249 | Boolean | 250 |false |
251 | Enables displaying the IGTV feed if available. Not compatible when loading a tag or from GraphQL API with user_id | 252 |
255 | max_tries
256 | |
257 | number [Int] | 258 |8 |
259 | Number of tries to fetch Instagram data until throwing. Useful to avoid arbitrary CORS issues. | 260 |
263 | styling
264 | |
265 | Boolean | 266 |true |
267 | Enables default inline CSS styles | 268 |
271 | items
272 | |
273 | number [Int] | 274 |8 |
275 | Number of items to display. Up to 12 for users, up to 72 for tags | 276 |
279 | items_per_row
280 | |
281 | number [Int] | 282 |4 |
283 | Number of items that will be displayed for each row | 284 |
287 | lazy_load
288 | |
289 | Boolean | 290 |false |
291 | Enable lazy load of images using native web attribute loading="lazy" on img elements | 292 |
295 | margin
296 | |
297 | number [Float] | 298 |0.5 |
299 | Margin (percentage) between items in gallery/igtv | 300 |
303 | image_size
304 | |
305 | number [Int] | 306 |640 |
307 | Native resolution of the images that will be displayed in the gallery. Accepted values [150, 240, 320, 480, 640]. Does not apply to video previews. | 308 |
311 | host
312 | |
313 | String [url] | 314 |https://www.instagram.com/ |
315 |
316 | URL where to fetch the data. Useful if instagram changes CORS policy. Recommended as Instagram is CORS restricted again. Set to: 317 | 'https://images' + ~~(Math.random() * 3333) + '-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https://www.instagram.com/' 318 | |
319 |
322 | cache_time
323 | |
324 | number [Int] | 325 |360 |
326 | Instagram response cache expiry time in minutes. Increase this if you get banned too often. | 327 |
330 | on_error
331 | |
332 | function(error_description, error_code) | 333 |console.error |
334 | Function that will be triggered when an error ocurs. Error codes: 335 |1: No username nor tag defined 336 |2: No container nor callback defined 337 |3: Profile is age restricted 338 |4: Network banned 339 |5: Request error 340 | |
341 |
Don't like it? Check other examples!
410 | 411 |<script src="jquery.instagramFeed.min.js"></script>
414 | <script>
415 | (function($){
416 | $(window).on('load', function(){
417 | $.instagramFeed({
418 | 'username': 'instagram',
419 | 'container': "#instagram-feed1",
420 | 'display_profile': true,
421 | 'display_biography': true,
422 | 'display_gallery': true,
423 | 'display_captions': true,
424 | 'max_tries': 8,
425 | 'callback': null,
426 | 'styling': true,
427 | 'items': 8,
428 | 'items_per_row': 4,
429 | 'margin': 1,
430 | 'lazy_load': true,
431 | 'on_error': console.error
432 | });
433 | });
434 | })(jQuery);
435 | </script>
436 |
437 | Disable display_profile and display_biography
444 | 445 |<script src="jquery.instagramFeed.min.js"></script>
448 | <script>
449 | (function($){
450 | $(window).on('load', function(){
451 | $.instagramFeed({
452 | 'username': 'github',
453 | 'container': "#instagram-feed2",
454 | 'display_profile': false,
455 | 'display_biography': false,
456 | 'display_gallery': true,
457 | 'display_captions': false,
458 | 'callback': null,
459 | 'styling': true,
460 | 'items': 8,
461 | 'items_per_row': 4,
462 | 'margin': 1
463 | });
464 | });
465 | })(jQuery);
466 | </script>
467 |
468 | Change items, items_per_row and margin
475 | 476 |<script src="jquery.instagramFeed.min.js"></script>
479 | <script>
480 | (function($){
481 | $(window).on('load', function(){
482 | $.instagramFeed({
483 | 'username': 'zara',
484 | 'container': "#instagram-feed3",
485 | 'display_profile': false,
486 | 'display_biography': false,
487 | 'display_gallery': true,
488 | 'display_captions': false,
489 | 'callback': null,
490 | 'styling': true,
491 | 'items': 12,
492 | 'items_per_row': 6,
493 | 'margin': 0.25
494 | });
495 | });
496 | })(jQuery);
497 | </script>
498 |
499 | Use tag instead of username.
506 | 507 |<script src="jquery.instagramFeed.min.js"></script>
510 | <script >
511 | (function($){
512 | $(window).on('load', function(){
513 | $.instagramFeed({
514 | 'tag': 'paradise',
515 | 'container': "#instagram-feed4",
516 | 'display_profile': true,
517 | 'display_gallery': true,
518 | 'display_captions': true,
519 | 'items': 100,
520 | 'items_per_row': 5,
521 | 'margin': 0.5
522 | });
523 | });
524 | })(jQuery);
525 | </script>
526 |
527 | Enable display_igtv. What is IGTV?
534 | 535 |<script src="jquery.instagramFeed.min.js"></script>
538 | <script >
539 | (function($){
540 | $(window).on('load', function(){
541 | $.instagramFeed({
542 | 'username': 'fcbarcelona',
543 | 'container': "#instagram-feed5",
544 | 'display_profile': false,
545 | 'display_biography': false,
546 | 'display_gallery': false,
547 | 'display_captions': false,
548 | 'display_igtv': true,
549 | 'callback': null,
550 | 'styling': true,
551 | 'items': 8,
552 | 'items_per_row': 4,
553 | 'margin': 1
554 | });
555 | });
556 | })(jQuery);
557 | </script>
558 |
559 | Use user_id to fetch data directly from Instagram GraphQL API
567 |To find the user_id based on the username, use following URL
568 | https://www.instagram.com/web/search/topsearch/?query=<username>
The result page will contain text starting with such structure
570 | {"users":[{"position":0,"user":{"pk":"<user_id>","username":"<username>..."
Where <user_id> is the user_id we are looking for.
572 | 573 |<script src="jquery.instagramFeed.min.js"></script>
576 | <script>
577 | (function($){
578 | $(window).on('load', function(){
579 | $.instagramFeed({
580 | 'user_id': '2220311520',
581 | 'container': "#instagram-feed6",
582 | 'display_gallery': true,
583 | 'display_captions': true,
584 | 'styling': true,
585 | 'items': 18,
586 | 'items_per_row': 3,
587 | 'margin': 1
588 | });
589 | });
590 | })(jQuery);
591 | </script>
592 |
593 | Make your owns disabling styling
600 |This is the html you will have (Note we have enabled profile and biography in this case).
602 |<div class="instagram_profile">
603 | <img class="instagram_profile_image" src="..." alt="Instagram profile pic">
604 | <p class="instagram_username">@Instagram (<a href="...">@instagram</a>)</p>
605 | <p class="instagram_biography">....</p>
606 | </div>
607 | <div class="instagram_gallery">
608 | <a href="https://www.instagram.com/p/Bh-P3IoDxyB" rel="noopener" target="_blank">
609 | <img src="..." alt="instagram instagram image 0" />
610 | </a>
611 | ...
612 | </div>
613 | <div class="instagram_igtv">
614 | <a href="https://www.instagram.com/p/Bh-P3IoDxyB" rel="noopener" target="_blank">
615 | <img src="..." alt="instagram instagram image 0" />
616 | </a>
617 | ...
618 | </div>
619 |
620 | <script src="jquery.instagramFeed.min.js"></script>
624 | <script>
625 | (function($){
626 | $(window).on('load', function(){
627 | $.instagramFeed({
628 | 'username': 'instagram',
629 | 'container': "#instagram-feed3",
630 | 'display_profile': true,
631 | 'display_biography': true,
632 | 'display_gallery': true,
633 | 'display_captions': false,
634 | 'display_igtv': true,
635 | 'callback': null,
636 | 'styling': false,
637 | 'items': 12,
638 | });
639 | });
640 | })(jQuery);
641 | </script>
642 |
643 | Define a callback and do not define a container
650 |This is the format you will get.
652 |
653 |
654 | <script type="text/javascript" src="jquery.instagramFeed.min.js"></script>
658 | <script type="text/javascript">
659 | (function($){
660 | $(window).on('load', function(){
661 | $.instagramFeed({
662 | 'username': 'instagram',
663 | 'callback': function(data){
664 | $('#jsonHere').html(JSON.stringify(data, null, 2));
665 | }
666 | });
667 | });
668 | })(jQuery);
669 | </script>
670 |
671 | @" + data.full_name + " (@" + options.username + ")
"; 273 | if(options.display_biography){ 274 | html += "" + data.biography + "
"; 275 | } 276 | }else if(options.type == "location"){ 277 | html += ""; 278 | } 279 | html += "This profile is private
'; 288 | } else { 289 | var image_index = typeof image_sizes[options.image_size] !== "undefined" ? image_sizes[options.image_size] : image_sizes[640], 290 | imgs = (data.edge_owner_to_timeline_media || data.edge_hashtag_to_media || data.edge_location_to_media).edges, 291 | max = (imgs.length > options.items) ? options.items : imgs.length; 292 | 293 | html += "@"+e.full_name+" (@"+d.username+")
",d.display_biography&&(g+=""+e.biography+"
")):"location"==d.type&&(g+=""),g+="This profile is private
";else{var j="undefined"==typeof k[d.image_size]?k[640]:k[d.image_size],l=(e.edge_owner_to_timeline_media||e.edge_hashtag_to_media||e.edge_location_to_media).edges,m=l.length>d.items?d.items:l.length;g+="