I have rails app. I added og tags for Facebook, google +, and Vkontakte. And I need to add possibility to share to LinkedIn too. But I don't understand why LinkedIn don't pick my OG tags.
My html:
= tag :meta, property: 'og:url', content: 'https://myapp.com/app'
= tag :meta, property: 'og:title', content: 'MyApp'
= tag :meta, property: 'og:description', content: 'You can always find a my app !'
= tag :meta, property: 'og:image', content: "https://myapp.com#{image_path('backgrounds/desk.jpg')}"
And facebook, g+, vk works perfectly, but linked in don't fetch any information from my website.
Any advise?
I had the same problem: everything worked except for LinkedIn on our https-only website. The problem was that ServerName and ServerAlias were not set in the Apache config file (default-ssl in our case).
You can use the Twitter card validator to check your SSL-settings (https://cards-dev.twitter.com/validator), if this throws an error adjust your Apache config.
You find additional information here: SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0
and here: Making your site shareable on LinkedIn
Interesting! You made your post on March 10, 2017. Support for og: tags at LinkedIn was only officially added and released on March 23, 2017; the feature just 13 days away!
The following formats are now all supported...
<meta property='og:title' content='Title of the article"/>
<meta property='og:image' content='//media.example.com/ 1234567.jpg"/>
<meta property='og:description' content='Description that will show in the preview"/>
<meta property='og:url' content='//www.example.com/URL of the article" />
Source: Official LinkedIn Documentation: Making Your Website Shareable on LinkedIn.
Works great for me:
If you want to verify that you have the tags in place correctly in your <head> block of HTML, try testing the page you're sharing at LinkedIn Post Inspector.
Related
We have a native iOS app that we're trying to add Sign In With Apple to. Everything I can find says we need to use the Service ID as the client_id. The problem is that when we implement the iOS part as in several articles out there (I'll reference some at the end of the post) it seems to use the Bundle ID as the client_id. At least that's what is in the "aud" field in the token we get. Then when we try and validate the token it fails because the validation is expecting the Service ID. Is there a way to tell it to use the Service ID or do I have to change my validation code to use the Bundle ID?
I've also setup a Javascript test Sign In With Apple page that uses the Service ID as the client_id and everything works as expected. Here's the code for that as a reference:
<html>
<head>
</head>
<body>
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script type="text/javascript">
AppleID.auth.init({
clientId: 'com.myproject.serviceid',
scope: 'name email',
redirectURI: 'http://local.test:32775/signin-apple',
state: 'Some stuff'
});
</script>
</body>
</html>
References:
https://developer.apple.com/documentation/authenticationservices/implementing_user_authentication_with_sign_in_with_apple
https://fluffy.es/sign-in-with-apple-tutorial-ios/
https://developerinsider.co/ios-13-how-to-integrate-sign-in-with-apple-in-your-application/
If you are using Sign in with Apple on iOS, it will always return the bundle ID of the application (from my experience) in the "aud" field, you will have to change your validation code.
You could write another API route in your backend for iOS app, so that if the request comes from that route, its audience will be bundle ID and do different validation.
Hope this helps!
I would like to use the autoUpdater from electron-builder to update my apps. I'm not using Github Releases because I have a private repo and don't want to include the GH_TOKEN for security purposes. Instead I want to put the binaries and the latest.yml/latest-mac.yml files into a Google Storage Bucket.
I know that it is possible to use a generic provider to check for updates. But currently, I can't get electron-builder to even read the latest.yml. I've poured over the documentation and other github/stack overflow issues for hours and hours and haven't found anything to resolve this.
Here's the code I have in my main.js for electron/auto updater to set a new feed URL -
const data = {
provider: 'generic',
url: 'https://storage.cloud.google.com/my-project', //'my-project' is the name of the bucket
channel: 'latest',
};
autoUpdater.setFeedURL(data);
autoUpdater.autoDownload = false;
autoUpdater.checkForUpdates();
The built app plus the yml files are in that bucket. When I try to run my app, I get a huge error that basically just copies over the Google Cloud Storage HTML/CSS instead of reading and processing the latest.yml file...
Error: Error: Cannot parse update info from latest-mac.yml in the latest release artifacts (https://storage.cloud.google.com/my-project/latest-mac.yml?noCache=1dh4pdr5e): YAMLException: end of the stream or a document separator is expected at line 11, column 14:
font-family: 'Open Sans';
^
at generateError (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:167:10)
at throwError (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:173:9)
at readDocument (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:1539:5)
at loadDocuments (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:1575:5)
at load (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:1596:19)
at safeLoad (/Users/somelocation/documents/some-project/node_modules/js-yaml/lib/js-yaml/loader.js:1618:10)
at parseUpdateInfo (/Users/somelocation/documents/some-project/node_modules/electron-updater/out/providers/Provider.js:131:37)
at GenericProvider.getLatestVersion (/Users/somelocation/documents/some-project/node_modules/electron-updater/out/providers/GenericProvider.js:57:48)
at processTicksAndRejections (internal/process/task_queues.js:86:5)
at async MacUpdater.getUpdateInfoAndProvider (/Users/somelocation/documents/some-project/node_modules/electron-updater/out/AppUpdater.js:488:13), rawData:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=300, initial-scale=1" name="viewport">
<meta name="google-site-verification" content="LrdTUW9psUAMbh4Ia074-BPEVmcpBxF6Gwf0MSgQXZs">
<title>Sign in - Google Accounts</title>
Is it possible at all to read the files from a Google Cloud Storage bucket rather than S3 or Github? Also, I've already tried eliminating an extra lines or tabs from the yml file.
You should use GCP API instead of a browser URL.
This code worked for me:
"publish": {
"provider": "generic",
"url": "https://storage.googleapis.com/YOUR_BUCKET/"
}
https://cloud.google.com/storage/docs/json_api/v1 also can be used, but it requires OAuth
try to execute this code after the app 'ready' event.
app.on('ready', () => {
const feedURL = 'https://storage.cloud.google.com/my-project';
autoUpdater.setFeedURL(feedURL);
autoUpdater.checkForUpdates();
});
I want my Angular7 code to take a URL that contains a route and present desired updated meta tags to Twitter so that Twitter will render the correct social card.
Following standard practices for meta tags, which includes declaring in index.html header and updating in constructors of pages loaded by routes, I can see the correct updated values in the browser console, but twitter ignores those updates and uses the first meta tags from index.html.
From index.html...
<head>
<title>My Title</title>
<!-- Other Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="#myAccountName">
<meta name="twitter:title" content="My Title">
<meta name="twitter:description" content="A detailed description of the site">
<meta name="twitter:image" content="https://www.oursite.com/welcome.png">
From app.module.ts…
import { mySubComponent } from './components/mySub/mySub.component';
...
const appRoutes: Routes = [
...
{ path: 'mySubPage', component: mySubComponent },
...
From the .ts file for the module loaded by www.oursite.com/mySubPage...
import { Router, ActivatedRoute, Params } from '#angular/router';
import { Meta, Title } from '#angular/platform-browser';
#Component({
selector: 'app-mySub',
templateUrl: './mySub.component.html',
styleUrls: ['./mySub.component.css']
})
export class mySubComponent implements OnInit {
...
constructor(
...
public meta: Meta, public title: Title) {
meta.updateTag({ name: 'twitter:card', content: 'summary_large_image' });
meta.updateTag({ name: 'twitter:site', content: '#myAccountName});
meta.updateTag({ name: 'twitter:title', content: 'My Sub Title' });
meta.updateTag({ name: 'twitter:description', content: 'The descript of the sub page' });
meta.updateTag({ name: 'twitter:image', content: 'https://www.oursite.com/mySubPageLogo.png' });
}
When I run this in the browser and manually type the full URL with the route (www.oursite.com/mySubPage, the console Inspector shows all the correct settings...
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="#myAccountName">
<meta name="twitter:title" content="My Sub Title">
<meta name="twitter:description" content="The descript of the sub page">
<meta name="twitter:image" content="https://https://www.oursite.com/mySubPageLogo.png">
But the twitter card validator set to the exact same Sub URL shows the card from the main index.html and appears to ignore the updates from the route altogether.
By the way, I did attempt all steps to flush the twitter cache, and even waited for longer than 12 hours and tried again. But I can make an update to the main tags and the change shows up, so it's not a cache issue with twitter.
This following is from https://twittercommunity.com/t/not-whitelisted-unable-to-render-or-no-image-read-this-first/62736 It looks like unless someone knows of a different approach, they are basically saying we can't serve up different cards from different angular routes from the same app domain. You only get one. Notice they spell it out in the middle...
Before posting a Cards issue, please READ the following:
If you are posting about any issue with your site, please include a
link to the publically-accessible URL where your Card markup is
visible, or we will be unable to help you.
You should also make sure that you’ve checked the items below, and
perform your own troubleshooting before asking for additional help.
Posts that indicate that none of these checks have been performed will
not be prioritised for attention.
As of early 2018, cards no longer require whitelisting (including
player cards)
The not whitelisted error message from the Validator is misleading, and almost certainly means that the tool cannot see or
find any twitter:card markup in your page.
If you see a message saying that you need to submit your card for approval, you’ve probably specified an incorrect card type in the
markup.
Please review the following if you are having other issues:
when you view the source of your page, the expected Twitter Cards meta tags 581 are shown
NB at a minimum, your page must contain at least a twitter:card meta tag specifying a valid card type 370, or suitable OpenGraph
fallback tags 170.
if you execute curl -v -A Twitterbot at the command prompt, does your page still show the twitter:card tags in the section
of the page? Does your server return a 200 response code and a valid
Content-Type header?
is your page adding the tags after it is loaded, for instance using Javascript (e.g. Angular, Meteor, Google Tags Manager)? The
crawler and validator cannot execute Javascript and the tags must be
static.
is your site accessible by the Twitterbot/1.0 user-agent? Are all the files (including image files) accessible to Twitterbot? you should
check http://your-site-url/robots.txt 646 and ensure that it allows
access to our crawler. If your images are on a different domain, also
make sure you check the robots.txt file for that domain.
are you using a Wordpress (or other CMS/blogging platform) plugin? We provide our own official Wordpress plugin 614, but cannot easily
provide support for those built by third parties. Check that the
configuration includes all of the required tags. Avoid using multiple
plugins at the same time, as tags will override one another.
are you putting the top-level site URL into the Validator, or the specific URL where your markup is present? you’ll need to make sure
that you provide a link to where your Card markup is visible in the
page.
are you using a supported 370 Card type? Product, Gallery and Photo cards were deprecated in mid-2015 128. Is the card type spelled
correctly, or is there a typo?
if your image is not showing, is it accessible on a URL that is not blocked by your robots.txt file? Does it conform to our size
constraints? Are you using an absolute and full URL (including the
http protocol piece), not a relative one?
if you see a validator message about Fetching the page failed because other errors or similar, check your SSL configuration. The
certificate and server name must match (or be aliased to match) due to
Java security constraints. More in this thread 220.
are you using a fully qualified DNS domain name? The crawler does not support dotted IP addresses as domain references, and cannot
access localhost.
There is much more Troubleshooting 302 information on our Developer
site.
Looks like there's no work-around for Angular7 at this time. Apparently there can be only one card, served up statically from on index.html per angular domain name.
Are you using a firebase as a BaaS? If so I was able to get twitter to render cards by doing exactly what you were doing above(setting up a service or inserting Meta tags into components). this lesson helped me out https://fireship.io/lessons/angular-universal-firebase/ , but base on my issue besides it having anything to do with being firebase app, my universal would not serve into the browser under app-root. I did not have to render any meta tags in my default index.html. Check the tutorial above and see if that helps out your issue at all.
https://angular.io/guide/universal
// Sub-Component
import { Component, OnInit } from '#angular/core';
import { Title, Meta } from '#angular/platform-browser';
#Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss']
})
export class AboutComponent implements OnInit {
data = {
name: 'Michael Jordan',
bio: 'Former baseball player',
image: ''
};
constructor(private title: Title, private meta: Meta) {}
ngOnInit() {
this.title.setTitle(this.data.name);
this.meta.addTags([
{ name: 'twitter:card', content: 'summary' },
{ name: 'og:url', content: '/about' },
{ name: 'og:title', content: this.data.name },
{ name: 'og:description', content: this.data.bio },
{ name: 'og:image', content: this.data.image }
]);
}
}
I was able to connect with to Intuit using the Minimul/QboApi gem and get the "Connect to Quickbooks" button working with oauth2 based on the example provided on Github. However neither the gem nor the samples show how to implement single sign on with Intuit. In the example provided by Minimul, the Connect To Quickbooks button is produced by intuit's javascript found at https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere-1.3.5.js
and a setup script and the tag . The tag appears to have been deprecated. Or at least, it doesn't appear to do anything other than produce the button with the right text and logo on it.
But bottom line, I have been unable to find any documentation on the ipp.anywhere.js package, and not even sure if i's meant to used with oauth2 since it's not mentioned anywhere. I believe that the connect to intuit button does the right things, but the guidelines seem pretty strict about what that the button needs to say the right thing and have th eright logo or they will reject it in the store. They also seem to suggest that users are much more likely to try something if an SSO with Intuit workflow is enabled. Any help appreciated.
After some further work, I figured out a solution that can create a 'log in with Inuit button' , although it's a bit of a javascript hack. First, I determined that the only thing I really needed to change was the button image. In other respects the code behind ` works fine for either a "login with intuit" or "connect to intuit work flow" . The only problem is the button image.
Here is the code (adapted from Minimul/QboApi) to get access and oauth2 refresh tokens via a "Connect to Quickbooks" button.
Setup in the controller code in login or sessions controller:
def new
#app_center = QboApi::APP_CENTER_BASE # "https://appcenter.intuit.com"
state= SecureRandom.uuid.to_s
intuit_id = ENV["CLIENT_ID"]
intuit_secret = ENV["CLIENT_SECRET"]
client = Rack::OAuth2::Client.new(
identifier: intuit_id,
secret: intuit_secret,
redirect_uri: ENV["OAUTH_REDIRECT_URL"],
uthorization_endpoint:"https://appcenter.intuit.com/connect/oauth2",
token_endpoint: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
response_type: "code"
)
#make sure to include at least "openid profile email"
#in the scope to you can retrieve user info.
#uri = client.authorization_uri(scope: 'com.intuit.quickbooks.accounting openid profile email phone address', state: state)
end
Here is the code required to generate the button on the view. (The view needs to load jquery as well in order for the script to work.)
<script type="text/javascript" src="<%= #app_center %>/Content/IA/intuit.ipp.anywhere-1.3.5.js">
</script>
<script>
intuit.ipp.anywhere.setup({
grantUrl: "<%== #uri %>",
datasources: {
quickbooks: true,
payments: false
}
});
</script>
<div>
<ipp:connecttointuit></ipp:connecttointuit>
This code produces the following html on the page delivered to the client:
<ipp:connecttointuit>
Connect with QuickBooks
</ipp:connecttointuit>
This code produces a button with the Connect with QuickBooks image, and an event handler inside intuit.ipp.anywhere-1.3.5.js attaches itself to the click event.
The problem is that the button is styled by the class=intuitPlatformConnectButton attribute inside the generated <a> tag, so if you want a "login with intuit button instead of a connect with intuit button the class on the anchor needs to be changed to class='intuitPlatformLoginButtonHorizontal' but still needs to attach to the event handler defined for <ipp:connecttointuit>. The best solution that doesn't require mucking with intuit.ipp.anywhere is to create the connect button and hide it, and then create another tag styled with class=intuitPlatformLoginButtonHorizontal whose click event calls click on the hidden connect button. I use AngularJs on my login page, so I handle the click with ng-click, but it could be done simply with jquery alone.
new.html.erb:
<div>
</div>
<div>
<ipp:connecttointuit id="connectToIntuit" ng-hide="true">< </ipp:connecttointuit>
</div>
and the controller code:
$scope.intuit_login = function() {
let el = angular.element("#connectToIntuit:first-child")
el[0].firstChild.click();
}
This will result in a redirect upon authentication to the supplied redirect url, where you can use openid to get the user credentials.
I created a post in blogdown from a .Rmd file. The header of the file includes:
---
title: Social assistance and unemployment duration in Alberta
author: Blake Shaffer
date: '2018-11-30'
slug: caseload-duration
categories: []
tags: []
twitterImg: post/2018-11-29-caseload-duration-files/figure-html/unnamed-chunk-5-1.png
header:
caption: ''
image: '/caseload-duration-banner.png'
---
But when I tweet a link to the post, the image does not appear:
I am using blogdown via RStudio, and the hugo/gcashen-academic theme.
Is there something I am missing?
I ran your post though the Twitter Card Validator - https://cards-dev.twitter.com/validator
It seems to work - the image is displayed. Looking through the source for https://www.blakeshaffer.ca/post/caseload-duration/ I notice one possible problem on this line:
<meta name="twitter:image" content="http://blakeshaffer.ca/post/2018-11-29-caseload-duration_files/figure-html/unnamed-chunk-5-1.png" >
You should make sure that the image is referenced using https rather than just http