Google Sheets API: How to "publish to web" for embeddable sheet? - google-api

If I wanted to publish a Google Sheets spreadsheet so I could embed it on a page within an iframe, I would manually do the following:
Navigate to Google Drive
Open a spreadsheet
File > Publish To Web > Embed > Copy the generated iframe link into an html file
How would I programmatically achieve the above through the Google Sheets API using JavaScript on the front end? I'm generating spreadsheets on the fly in my application and want to immediately embed them on the page once created.
Once the sheet is created, I can dynamically create an iframe element with the necessary attributes (the sheets ID, among others). That throws an error. From this question, it looks like a sheet needs to have a published: true attribute or something, but that requires using the Drive API - I'm trying to avoid that. Is this possible to handle only through the Sheets API?

After searching through the entire Sheets API, googling, and just general soul-searching, I had no choice but to include the Drive API and use it to do my bidding. Here's the solution I came up with. Hope this helps someone else out there!
Used this script from Google for the client-side JS library in the index.html file:
<body>
...
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
Then for the JS stuff:
// Cache the api's into variables.
var sheets = gapi.client.sheets;
var drive = gapi.client.drive;
// 1. CREATE NEW SPREADSHEET
sheets.spreadsheets.create({
properties: {
title: 'new-sheet'
}
}).then(function(newSpreadSheet) {
var id = newSpreadSheet.result.spreadsheetId;
// 2. PUBLISH SPREADSHEAT VIA DRIVE API
drive.revisions.update({
fileId: id,
revisionId: 1
}, {
published: true, // <-- This is where the magic happens!
publishAuto: true
}).then(function() {
// 3. DISPLAY SPREADSHEET ON PAGE VIA IFRAME
var iframe = [
'<iframe ',
'src="https://docs.google.com/spreadsheets/d/',
id,
'/pubhtml?widget=true&headers=false&embedded=true"></iframe>'
].join('');
// We're using jQuery on the page, but you get the idea.
$('#container').html($(iframe));
});
});

As you have concluded, it is not possible through the Sheets API today and is only possible through the Drive API (using the PATCH https://www.googleapis.com/drive/v3/files/fileId/revisions/revisionId request, documented at https://developers.google.com/drive/v3/reference/revisions/update).

Related

I'm trying to display Tableau workbooks on my webpage, but the result is blank page

My web is Laravel-VueJs App, I managed to sign in to Tableau server automatically in the background, (but without getting Auth tickets (I'm not sure if I need tickets for Javascript API yet), I'm trying to show my workbooks on my web page but getting blank page without any error, however this is my code
first added Javascript API in my app.blade.php
<script type="text/javascript" src="https://my-server-url/javascripts/api/tableau-2.8.0.min.js"></script>
and this is the Vue component where I need to show workbooks
<template>
<div>
<div
ref="tableau"
style="width:800px; height:700px;"
/>
</div>
</template>
<script>
export default {
name: "TableauWorkbookShow",
props: {
url: {
type: String,
required: true,
},
},
mounted(){
this.initViz();
},
methods: {
initViz() {
// url looks something like this: https://my-server-url/#/site/my-site-name/views/workbook-name/view-name
var viz = new tableau.Viz(this.$refs.tableau, this.url);
}
}
};
</script>
no errors, neither info on the page, anything else i need to consider here ? and should I add Auth tickets to the url to get workbooks or the url as it is now is fine to work?
One way to test would be to use the Embed code directly from the workbook on Server.
Click Share
Then click Copy Embed Code.
Paste this code directly into your html/view. It should have everything included to populate your dashboard into a webpage.
If this works, you know that your overall auth is working and you can troubleshoot the differences of your js to the embed code.
If auth doesn't work you should still see this screen if your js/html is working correctly.

How to use Google Picker with Google Drive using flutter

I can't find any resource to embed google Picker in a flutter to upload a doc to Google drive. Can any provide me with an example of how to integrate Google Picker to Flutter?
Same issue here, you can use file_picker:
final result = await FilePicker.platform.pickFiles();
It will navigate user to an UI for selecting files including other app's files, i.e. google drive.
BTW, you should request permissions before picking the file:
final googleSignIn = GoogleSignIn(scopes: []);
await googleSignIn.signIn()
// request when you need it!
await googleSignIn.requestScopes([SheetsApi.spreadsheetsScope])
Found similar question here: File Picker for Google Drive Rest API for Android

Image hosted internally inaccessible on MS Teams client

We have enabled Bot Framework app in our corporate Teams and we want to use AdaptiveCards to present rich content to users. For example, we are sending AdaptiveImage containing url pointing to corporate image store.
Sample code:
new AdaptiveImage
{
Size = AdaptiveImageSize.Small,
Url = new Uri("https://corporate-storage.com/images/image1.png"), // This is image not hosted publicly.
AltText = "Some text"
}
This works fine in WebChat client as the url is just appended to the src attribute of the img HTML tag. However in MS Teams it seems that it is preprocessed by some weird proxy / MITM and the url results in:
https://urlp.asm.skype.com/v1/url/content?url=https%3a%2f%2fcorporate-proxy.com%2fimages%2fimage1.png
When we try to browse the url to see where why the picure is not rendered we see empty page with 502 response code in debugger.
Is there a way how to force MS Teams to not alter src attributes of pictures.
For rendering image in adaptive card, it has to be hosted in public content-delivery network (CDN). Here the official document link.
It worked in WebChat client because in browser your authentication is already cached where as in Teams App there is no cache and the image requires authentication.
You need to host the image in public domain or Azure Blob storage to make it work.
I also have not found a way to resolve that, some gays also ask about this problem.
So, I use tampermonkey to load a JS code piece like this.
// ==UserScript==
// #name New Userscript
// #namespace http://tampermonkey.net/
// #version 0.1
// #description try to take over the world!
// #author You
// #match https://teams.microsoft.com/*
// #icon https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// #grant none
// ==/UserScript==
(function() {
'use strict';
setInterval(function(){
$('img').each(function(){
if($(this).attr('src').startsWith("https://urlp.asm.skype.com/v1/url/content?url=https%3a%2f%2fp.datadoghq.com")){
let datadogUrl=$(this).attr('src').replace("https://urlp.asm.skype.com/v1/url/content?url=","")
datadogUrl=decodeURIComponent(datadogUrl)
$(this).attr('src', datadogUrl);
}
})
}, 5000);
})();
And use Teams Web, not Teams App.

Error: No reCAPTCHA clients exist (reCAPTCHA v3)

I've integrated reCAPTCHA v3 in one of my forms. In onload, there's a token produced and google captcha logo in the bottom right corner. But when I submit the form, in console there is an error shown, "Error: No reCAPTCHA clients exist". Also, it seems, no data is fetched by "g-recaptcha-response" and $_POST["g-recaptcha-response"] remains empty.
Here is the sample code:
<script type="text/javascript">
var ReCaptchaCallbackV3 = function() {
grecaptcha.ready(function() {
grecaptcha.execute("site_key").then(function(token) {
console.log("v3 Token: " + token);
});
});
};
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=ReCaptchaCallbackV3&render=site_key"></script>
It doesn't produce any "g-recaptcha-response" when the form is submitted.
I don't know much about google reCaptcha. I've followed the documentation provided by them and used a site and a secret key in the proper way.
Can anybody please tell me where might be the problem and what is the possible solution?
I believe this error occurs when the reCaptcha api.js loads, but your container is not present on the page yet (at least for v2). I had this error occur in a React app when I navigated to the page rather than loading it as the first on. Instead of using render=explicit and using a global namespace onLoadCallback, I was able to resolve it by rendering the captcha element manually.
Instead of creating a <div class="g-recaptcha"></div>, give the container div an id only (<div id="recaptcha-container"></div>) and render it in your JS code (e.g. in componentDidMount for a React app):
grecaptcha.ready(function() {
grecaptcha.render("recaptcha-container", {
"sitekey": "your-site-key"
});
});
Have you tried loading the script before trying to send the request?
<script src="https://www.google.com/recaptcha/api.js?onload=ReCaptchaCallbackV3&render=site_key"></script>
<script type="text/javascript">
var ReCaptchaCallbackV3 = function() {
grecaptcha.ready(function() {
grecaptcha.execute("site_key").then(function(token) {
console.log("v3 Token: " + token);
});
});
};
</script>
When I came across this problem with reCAPTCHA v3, it was because I didn't pass it the correct site key.
This also happens in Recaptcha 2 before user interacts with it. So, I have a submit button that triggers a JS function that checks the value of recaptcha. To solve the no client exists problem, I did:
try {
data["reCaptcha"] = grecaptcha.getResponse();
} catch (err) {
data["reCaptcha"] = "";
}
The data object then gets sent to a back-end script that validates the recaptcha. The back-end also checks for the field being empty.
I had this problem because I was calling grecaptcha.reset(); when there wasn't any Recaptcha active on the site
grecaptcha.reset();
recaptcha__en.js:507 Uncaught Error: No reCAPTCHA clients exist.
at MX (recaptcha__en.js:507)
at Object.Zn [as reset] (recaptcha__en.js:514)
at <anonymous>:1:13
I was using React and only rendering my captcha container sometimes. Fixed by hiding the captcha button instead of not rendering it.
In my case grecaptcha.reset(); was present from previous code snippet, and I was programmatically invoking it.
As the captcha verification is going on the fly every time. Resetting wasn't required.
After eliminating this grecaptcha.reset(); my code works perfectly fine.
Maybe this hint can help someone.
We received this because we have a second environment with another domain and forgot to add this domain to the reCaptcha admin site. The solution was to add the new domain to the settings.
The steps are
Open www.google/recaptcha/admin/site
Select the site you're working on
Click on the settings gear
Add the domain in its respective section

Google console fetch & render does display AJAX fetched content

I have published a reactjs website that relies on AJAX requests (POST requests on a graphQL API if that's relevant) to display data.
Using google console fetch & render service, I can see that only my components that do not have to call any API are rendered. Any AJAX based component is not rendered at all.
Google fetch & render does show me 2 rendering pictures of my website (google vs visitor), but both are missing AJAX content.
Is server rendering mandatory in this case ?
I do not have a robots.txt file.
I'm doing something like:
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { observable, runInAction } from 'mobx';
import axios from 'axios';
import ContributorList from '~/components/global/ContributorList';
import type { User } from '~/types';
import CSSModules from 'react-css-modules';
import styles from './style.less';
#observer
#CSSModules(styles)
export default class Footer extends Component {
#observable contributors: Array<User> = [];
async loadContributors () {
const { data: {
data: data
} } = await axios.post('/', {
query: `
{
users {
id,
name,
slug,
avatar {
secure_url
}
}
}
`
});
runInAction( () => {
this.contributors = data.users;
});
}
componentDidMount () {
this.loadContributors();
}
render () {
return (
<div styleName='contributors'>
{ 'Static content' }
<ContributorList
contributors={ this.contributors }
/>
</div>
);
}
};
In my browser, I can see everything fine ('Static content' + contributors that rare fetched asynchronously). But with google fetch and render, I see 2 screenshots with only 'Static content' displayed.
As a result, my dynamic content does not appear in google search results.
Now all the people are talking about progressive web apps (PWA) which rely on Ajax and rendering the content of the website using client side techniques.
But these techniques are not SEO friendly at all, since Google can't index the classic Ajax request and most of the modern requests.
Since you are using ReactJs, and you want Google to index your website you have to use server side rendering.
This will slow down your website and at the same time Google can crawl and index all your pages, also the user can view it on any device, even the old devices.
When you want to build a PWA or modern web app in general, you have to go back to the basics, for an old technique called graceful degration, which mean if you disabled the JS from your browser still you can see the content and all the functions on your website are work.
This is the same way Google crawl and index your website.
There are many recommendations from Google regarding crawling Ajax content:
Use clean URL structure and avoid using JS links(javascript:void(0);)
Load all the using server side rendering
Make sure that your website is working on all devices(responsive)
Submit XML sitemap
Use canonical links in if you have more than one URL structure (which is not recommended)
We are working on a new project similar to yours, built using reactjs and it will be one of the first PWAs in the world that Google can crawl it like any other website by doing the above points.
Also Google have published an article on their webmaster blog talking about the PWA and any modern web app like yours.
For more details check this link
https://webmasters.googleblog.com/2016/11/building-indexable-progressive-web-apps.html
Regarding the robots.txt file, its recommended to add robots for any website even if you don't have pages to block, but you may want to block the ajax requests and other annoying crawlers.

Resources