Rich Results test returning `null` and "unnamed" for Breadcrumb in schema, however it is appearing correctly in Google Structured data testing tool - css-selectors

I am trying to implement structured data for breadcrumbs correctly. Rich results is calling my 3rd item in the list "unnamed" and subsequently causes the actual SERP to return null in breadcrumbs. I am calling the 3rd item using a css selector grabbing the breadcrumb from the DOM in GTM. What am I missing? Why is google returning null for only the 3rd element in the breadcrumb list?
Rich Results Page output
Google Structured Data testing tool output
<script>
(function (){
var jsonData =
{
"#context": "http://schema.org",
"#type": "BreadcrumbList",
"itemListElement":
[
{
"#type": "ListItem",
"position": 1,
"item":
{
"#id": "https://www.globalknowledge.com/us-en/",
"name": "Home"
}
},
{
"#type": "ListItem",
"position": 2,
"item":
{
"#id": "https://www.globalknowledge.com/us-en/training/course-catalog/",
"name": "Course Catalog"
}
},
{
"#type": "ListItem",
"position": 3,
"item":
{
"#id": {{Page URL}},
"name": "{{Breadcrumb list 2-Version2}}"
}
}
]
};
var el = document.createElement('script');
el.type = 'application/ld+json';
el.innerHTML = JSON.stringify(jsonData);
document.head.appendChild(el);
})();
</script>
Note: Breadcrumb list 2-Version2 =
.breadcrumbs .breadcrumb-child > .breadcrumb-title
Rendered by GTM into this:
<script type="application/ld+json">{"#context":"http://schema.org","#type":"BreadcrumbList","itemListElement":[{"#type":"ListItem","position":1,"item":{"#id":"https://www.globalknowledge.com/us-en/","name":"Home"}},{"#type":"ListItem","position":2,"item":{"#id":"https://www.globalknowledge.com/us-en/training/course-catalog/","name":"Course Catalog"}},{"#type":"ListItem","position":3,"item":{"#id":"https://www.globalknowledge.com/us-en/training/course-catalog/brands/itil/","name":"null"}}]}

<script>
(function (){
var jsonData =
{
"#context": "http://schema.org",
"#type": "BreadcrumbList",
"name": "WEBPAGE_NAME",
"itemListElement":
You can add the name attribute to the Breadcrumblist and unnamed item will change to the value you set.
"name": "WEBPAGE_NAME",

Related

WebExtensions: browser.webRequest.onCompleted never fires

I'm using the Firefox WebExtensions API with the following background script
var log = console.log.bind(console)
log('hello world from browser extension')
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/onCompleted
var filter = { urls: '<all_urls>' }
var extraInfoSpec = ['tlsInfo', 'responseHeaders']
browser.webRequest.onCompleted.addListener(function(details){
log(`Woo got a request, here's the details!`, details)
}, filter, extraInfoSpec)
log('Added listener')
After loading the script from about:debugging, I see the following output in DevTools:
hello world from browser extension
I do not see any output- there is no data from browser.webRequest.onCompleted.addListener and there is no 'Added listener' message.
How do I make browser.webRequest.onCompleted work?
For completeness, my manifest.json is below:
{
"manifest_version": 2,
"name": "Test extension",
"version": "1.0",
"description": "Test extension.",
"icons": {
"48": "icons/border-48.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"permissions": [
"webRequest",
"webRequestBlocking"
]
}
The webRequest API is only available to background scripts. You seem to using it inside a content script.
urls in var filter = { urls: '<all_urls>' } needs to be be an array ['<all_urls>'].
'tlsInfo' in extraInfoSpec doesn't exist, I don't know where it comes from.
You need to specify an additional <all_urls> permission in your manifest.
script.js
var filter = { urls: ['<all_urls>'] }
var extraInfoSpec = ['responseHeaders']
browser.webRequest.onCompleted.addListener(function(details){
console.log(`Woo got a request, here's the details!`, details)
}, filter, extraInfoSpec)
console.log('Added listener')
manifest.json
{
"manifest_version": 2,
"name": "Test extension",
"version": "1.0",
"description": "Test extension.",
"icons": {
"48": "icons/border-48.png"
},
"background": {
"scripts": ["script.js"]
},
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>"
]
}

Dealing duplicate image data in React Native

I'm building 'Comments Detail page' which is a list view for comments in a single post (basically it's just facebook comments page).
I generated this JSON response data below, and as you can see, there are duplicate image urls. It means that if same user comments 100 times on a post, it needs to get image data from AWS 100 times rather than 1 time.
Maybe it's over-engineering? How do you guys deal with this?
Here is JSON data
{
"comments": [{
"id": 4,
"user": {
"image": "https://xxx.s3.amazonaws.com:443/-",
"id": 1,
"username": "jbaek73"
},
"content": "Edited!",
"publish": "2017-09-18T12:11:41.002838Z",
"updated": "2017-09-19T08:16:25.408756Z",
"reply_count": 1
},
{
"id": 13,
"user": {
"image": "https://xxx.s3.amazonaws.com:443/-",
"id": 1,
"username": "jbaek73"
},
"content": "Neaa!",
"publish": "2017-09-18T14:12:51.876523Z",
"updated": "2017-09-18T14:12:51.876600Z",
"reply_count": 0
},
{
"id": 14,
"user": {
"image": "https://xxx.s3.amazonaws.com:443/random",
"id": 5,
"username": "koreana"
},
"content": "Newa!",
"publish": "2017-09-19T08:16:35.190351Z",
"updated": "2017-09-19T08:16:35.190398Z",
"reply_count": 0
},
In this case, i would create an image object with all the required images and the user id as key:
randomFuntionName() { //you can call after you get your json
var img = []
comments.forEach((element) => { //comments are comming from your json btw
if (img[element.user.id] == null) {
img[element.user.id] = require(element.user.image)
}
})
this.setState({img})
}
render() {
//this part is only for example, you need to dynamicaly change userID
return (<Image source={this.state.img[userId]}/>)
}
This should do the work, but didn't tested it in app.

NoSQL Structure for handling labeled tags

Currently I have a hundreds of thousands of files like so:
{
"_id": "1234567890",
"type": "file",
"name": "Demo File",
"file_type": "application/pdf",
"size": "1400",
"timestamp": "1491421149",
"folder_id": "root"
}
Currently, I index all the names, and a client can search for files based on the name of the file. These files also have tags that need to be associated with the file but they also have specific labels.
An example would be:
{
"tags": [
{ "client": "john doe" },
{ "office": "virginia" },
{ "ssn": "1234" }
]
}
Is adding the tags array to my above file object the ideal solution if I want to be able to search thousands of files with a client of John Doe?
The only other solution I can think of is having something an object per tag and having an array of file ID's associated with each tag like so:
{
"_id": "11111111",
"type": "tag",
"label": "client",
"items": [
"1234567890",
"1222222222",
"1333333333"
]
}
With this being a LOT of objects I need to add tags to, I'd rather do it the most efficient way possible FIRST so I don't have to backtrack in the near future when I start running into issues.
Any guidance would be greatly appreciated.
Your original design, with a tags array, works well with Cloudant Search: https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#search.
With this approach you would define a single design document that will index any tag in the tags array. You do not have to create different views for different tags and you can use the Lucene syntax for queries: http://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Overview.
So, using your example, if you have a document that looks like this with tags:
{
"_id": "1234567890",
"type": "file",
"name": "Demo File",
"file_type": "application/pdf",
"size": "1400",
"timestamp": "1491421149",
"folder_id": "root",
"tags": [
{ "client": "john doe" },
{ "office": "virginia" },
{ "ssn": "1234" }
]
}
You can create a design document that indexes each tag like so:
{
"_id": "_design/searchFiles",
"views": {},
"language": "javascript",
"indexes": {
"byTag": {
"analyzer": "standard",
"index": "function (doc) {\n if (doc.type === \"file\" && doc.tags) {\n for (var i=0; i<doc.tags.length; i++) {\n for (var name in doc.tags[i]) {\n index(name, doc.tags[i][name]);\n }\n }\n }\n}"
}
}
}
The function looks like this:
function (doc) {
if (doc.type === "file" && doc.tags) {
for (var i=0; i<doc.tags.length; i++) {
for (var name in doc.tags[i]) {
index(name, doc.tags[i][name]);
}
}
}
}
Then you would search like this:
https://your_cloudant_account.cloudant.com/your_db/_design/searchFiles/_search/byTag
?q=client:jack+OR+office:virginia
&include_docs=true
The solution, that comes into my mind would be using map reduce functions.
To do that, you would add the tags to your original document:
{
"_id": "1234567890",
"type": "file",
"name": "Demo File",
"file_type": "application/pdf",
"size": "1400",
"timestamp": "1491421149",
"folder_id": "root",
"client": "john",
...
}
Afterwards, you can create a design document, that looks like this:
{
"_id": "_design/query",
"views": {
"byClient": {
"map": "function(doc) { if(doc.client) { emit(doc.client, doc._id) }}"
}
}
}
After the view is processed, you can open it with
GET /YOURDB/_design/query/_view/byClient?key="john"
By adding the query parameter include_docs=true, the whole document will be returned, instead of the id.
You can also write your tags into an tags attribute, but you have to update the map function to match the new design.
More information about views can be found here:
http://docs.couchdb.org/en/2.0.0/api/ddoc/views.html

empty array in angular-schema-form

I'm using angular-schema-form in my project and trying to add an empty array in my model.
I expected that array type schema form will not contain any items but it actually pushed one object in my array and showed it in from.
How can I init form with no items in array?
html
<div ng-app="app" ng-controller="Controller as ctr">
<form sf-schema="ctr.schema" sf-form="ctr.form" sf-model="ctr.model"></form>
{{ctr.model.comments}} - Where this object come from? This array was empty. Is it possible to keep it empty on load?
</div>
js
var myApp = angular.module('app', ['schemaForm'])
.controller("Controller", function() {
this.schema = {
"type": "object",
"title": "Comment",
"properties": {
"comments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"comment": {
"title": "Comment",
"type": "string",
"maxLength": 20,
"validationMessage": "Don't be greedy!"
}
}
}
}
}
};
this.form = [{
"key": "comments",
"items": [
"comments[]"
]
}];
this.model = {
comments: [] // Empty array defined
};
});
Jsfiddle
The value you are looking for is startEmpty: true this will avoid pre-populating the array with an object.
Angular Schema Form: Array Documentation
The pre-population is defaulted to ensure that the form fields within an array are available when the form loads. The startEmpty: true value can override this behaviour.

How to insert array of document in mongodb using node.js?

I want to insert array of document to mongodb using node.js but while inserting it's only inserting first data only.
[{
"userid": "5664",
"name": "Zero 2679",
"number": "1234562679",
"status": "contact",
"currentUserid": "Abcd"
},
{
"userid": "5665",
"name": "Zero 3649",
"number": "1234563649",
"status": "contact",
"currentUserid": "Xyz"
}]
Sample code
collection.insert([{"userid": userid,"name": name,"number": number,"status": status,"currentUserid": currentUserid}], function(err, docs) {
if (err) {
res.json({error : "database error"});
}else {
collection.find({currentUserid:currentUserid}).toArray(function(err, users) {
res.send(users);
});
}});
But it still inserting first value only can you please tell me how to insert all these documents.
Please kindly go through my post and suggest me some solution.
In your sample code you are adding only 1 user.
db.collection('myCollection').insert([doc1, doc2]); inserts two documents using bulk write.
See documentation here: https://docs.mongodb.org/manual/reference/method/db.collection.insert/
From your sample, you can do:
var data = [{
"userid": "5664",
"name": "Zero 2679",
"number": "1234562679",
"status": "contact",
"currentUserid": "Abcd"
},
{
"userid": "5665",
"name": "Zero 3649",
"number": "1234563649",
"status": "contact",
"currentUserid": "Xyz"
}];
db.collection('myCollection').insert(data)
.then(function() {
return db.collection('myCollection').find({number: {$in: ["1234563649", "1234562679"]}});
})
.then(function(res) {
console.log(res);
});

Resources