API V2 Search Bugs and Documentation Errors
Hi First the documentation error which will be relevant to the bugs I believe I've found. Documentation says select subject,body from messages where subject matches ('apples','oranges') should do a "one or more" search and return any messages containing either "apples" or "oranges". Instead, it only returns messages containing both. To do a"one or more" search you must instead add quotes around the entire list like this select subject,body from messages where subject matches "('apples','oranges')" This was corrected in this threadAPI v2 Search doesn't work - Atlas (khoros.com) but the documentation was never updated. BUG ONE Can't include a phrase exact match in a combinatorialsearch as discussed hereCombinatorial searches with LiQL (khoros.com) Example, I have 4 posts with the following in the body. I just took down my christmas tree It's January and christmas is over I just cut down a tree Since it is christmas time I should get a tree So,1 has the exact phrase "christmas tree", 4 has both words "christmas" and "tree" but not together, 3 has just the word "tree" and 2 has just the word "christmas". The query below onlyreturns number 1 with the exact phrase "christmas tree" as expected. SELECT subject, body FROM messages WHERE body MATCHES '"christmas tree"' If I want to combine that with the one or more search based on the documentation and also the correction discussed above it should look like the below query. (Because of the double sets of double quotes, I had to escape the inner set) SELECT id, subject FROM messages WHERE body MATCHES "('\"christmas tree\", bananas, cherries')" This should also only return number 1, but it also returns number 4 which has both "christmas" and "tree" separately. I have tried several variations on this, but none work the way expected. I can't find any way to return only number 1 (plus any messages with bananas or cherries). BUG TWO In a "one or more" search including a conjunction like "and" breaks the entire search. For example, let's say this search returns 2 messages with "apples" in the subject. SELECT id, subject FROM messages WHERE subject MATCHES "('apples', 'bananas')" Adding the word "and" to the list breaks this and it returns zero results even though there should still be 2. SELECT id, subject FROM messages WHERE subject MATCHES "('apples', 'bananas', 'and')" I'm guessing the intention was to ignore conjunctions and similar words in the search which makes sense but instead it ignores all words in the search. I stumbled upon a couple of other words with the same effect. The words "test" and "link" also break the search. I will open a support case about the above bugs, but wanted to share and see if anyone sees anything I'm missing or has a work around especially for bug one. I guess I should take a look at API V1 and see if I can use that to get the results I am looking for.Akenefick8 months agoGenius103Views2likes1CommentCustom pagination numbers aren't lining up
I'm getting a weird issue with a custom pagination component I'm trying to build. I have two tab items that I'm using a URL parameter to switch between. For each tab I'm using Freemarker to determine which tab is displaying and then build a feed of messages based on that. With the pagination, here's my code: <#if tabParam = "latest"> <#assign pageSize=settings.name.get("layout.messages_per_page_linear")?number /> <#assign pageNum=webuisupport.path.parameters.name.get("page", 1 ) /> <#assign paginationOffset=(pageNum - 1) * pageSize /> <#include "forum_feed_macro" /> <#assign msgCountQry=rest("2.0","/search?q=" + "SELECT count(*) FROM messages WHERE board.id='${currentBoard}' AND depth=0"?url).data.count /> <#assign res = liql(rest_20, "SELECT ${querySelect} FROM messages where board.id = '${currentBoard}' AND depth=0 ORDER BY post_time desc LIMIT ${pageSize} OFFSET ${paginationOffset}") /> <@renderListResponse type="message" response=res render=messageRenderFullMessage /> <#assign pageable_item=webuisupport.paging.pageableItem.setCurrentPageNumber(pageNum).setItemsPerPage(pageSize).setTotalItems(msgCountQry?number).setPagingMode("enumerated").build /> <@component id="common.widget.pager" pageableItem=pageable_item /> </#if> <#if tabParam = "activity"> <#assign pageSize=settings.name.get("layout.messages_per_page_linear")?number /> <#assign pageNum=webuisupport.path.parameters.name.get("page", 1 ) /> <#assign paginationOffset=(pageNum - 1) * pageSize /> <#include "forum_feed_macro" /> <#assign msgCountQryAll=rest("2.0","/search?q=" + "SELECT count(*) FROM messages WHERE board.id='${currentBoard}'"?url).data.count /> <#assign res = liql(rest_20, "SELECT ${querySelect} FROM messages where board.id = '${currentBoard}' ORDER BY post_time desc LIMIT ${pageSize} OFFSET ${paginationOffset}") /> <@renderListResponse type="message" response=res render=messageRenderFullMessage /> <#assign pageable_item=webuisupport.paging.pageableItem.setCurrentPageNumber(pageNum).setItemsPerPage(pageSize).setTotalItems(msgCountQryAll?number).setPagingMode("enumerated").build /> <@component id="common.widget.pager" pageableItem=pageable_item /> </#if> My problem here is that the feed created within the second "if" statement, the pagination stops at page 8, even though it's displaying up to 25 pages available. The first section, however, does stop at page 8. I'm wondering if somehow something is getting crossed between the first and second sections. For reference, the variables in the second feed are as follows: "pageSize" = 4 msgCountQryAll = 98 I just don't understand what's going on with my code that's causing the pagination in the second section to get stuck at page 8 even though it's showing up to 25 pages in the pagination component.Natkinson8 months agoGenius312Views0likes9CommentsSCSS Issue Tracker
As there is no public issue tracker (afaik) or reporting workflow (other than support tickets and ideas), I'd like to collect some things that were found through hour-long trial end error (some including workarounds) so others trying to customize the platform hopefully don't have to jump trough the same hoops as I had to or at least might be able to find some information or workarounds regarding things that don't behave as advertised or expected. This topic isNOTa place to rant about the platform, the devs or the product (it's software after all, and software has bugs, we know that very well...). I will make a new reply to this post for each issue and link them in the topic message for easier access. Hope it helps somebody! PS:If you know about something similar and it's not yet listed below, please feel free to add your own reply to the original topic message using the template below as a rough guideline of what information to provide. If you'd like to comment on a bug, try to reply to that specific "issue" message (so technically a threaded view could be aggregated, it's not right here, I know...) and reference (via permalink!) the issue you're commenting on, otherwise it's going to be very confusing =)... Quoted fromhttps://community.khoros.com/t5/Developer-Discussion/API-amp-FreeMarker-Issue-Tracker/td-p/547711peterlu8 months agoChampion951Views6likes3CommentsShowing SVG images based on Forum language
I am trying to show an SVG image based on Forum language. I would like to know the best way to complete this. I have tried putting the SVG content in custom text. I would also like to know if this can be showen by using the language api check. In the meantime i will try to just upload the svg files as images and try based on custom text that way.122Views0likes2CommentsCreate Message API V2 Questions
I am working on a custom post page for our idea boards so we can add in some custom fields. I have most of it working fine but there are a few things on the out of the box post page I was wondering about. I am using API V2 as described here Create message (khoros.com). Is there any way to set these things with the same API call? ThanksAkenefick8 months agoGenius151Views0likes2CommentsHow to get only Messages where some specific custom field have value?
Hi Team, I have a custom field added by Khoros in the messages object, I want toget only Messages where that specific custom field has value. Sample query: select c_abcd from messages where c_abcd!="" I don't want to get all messages and then in the loop filter the messages which don't have any value. Is there any direct API or solution to get the messages where thec_abcdcustom field has some value? Any related replies would be appreciated. Regards Aman385Views0likes11CommentsCan I cache the JSON returned by an endpoint? Would like to not make the AJAX or API call repeatedly
I have an endpoint that calls an external API which returns JSON. It's for "related content" for a post. (Yes, I know Khoros has an OOTB and a componentized version of that already for Hermes, but I need to access our own DB of related content, which is reached through an API call.) My end goal is that each post on our Community have related content from this API but that it only gets called every day or so, and the related content is displayed from the cache. Let's just say the JSON is something like this: { [ { "author":"John", "title":"Some article" "url":"community/t5/Developer-Discussion/Caching-API-objects/m-p/217953" }, { "author":"Mary", "title":"Another article" "url":"community/t5/Developer-Discussion/dvice-on-performance-for-external-API-query/m-p/208726" } ] } That is currently the output of the endpoint. That data is consumed by a component <@liaAddScript> (function($) { $(document).ready(function() { $.get( "${my_endpoint_url}" ).done(function( data ) { console.log(data); }).fail(function() { console.log('fail'); }) }); })(LITHIUM.jQuery); </@liaAddScript> (I hate that the only way to get a component is through AJAX, I wish there were a server-side way to get the data. Unless you know another way to get endpoint data...?) I want to cache the results of the endpoint so that the external API call is not made repeatedly. We want the most efficient execution of this. Do I cache it in the endpoint or the component? What's the best practice in order to avoid multiple calls to the API? Please help a friend out with a code example so I can understand it better. I have found several questions about it here on Atlas but they are very old (2015-2018), not answered, or archived, and I'm not sure exactly how to apply it. lukis this one still relevant?https://community.khoros.com/t5/Developer-Discussion/Advice-on-performance-for-external-API-query/m-p/208726#M9485 Do you,luk,ClaudiusorAkenefickDougS (or anyone else) have some thoughts on this? ThanksSolvedisxtn8 months agoAdvisor232Views0likes5CommentsHow can I list and count ALL bookmarks in the system?
I have been asked to analyze bookmarks, to determine such things as How many users make use of the bookmark feature in Khoros? What is the maximum number of bookmarks for a user? What is the average number of bookmarks for users with bookmarks? To do this, I would normally use LiQL v2 API to do {{prod}}/api/2.0/search?q=select count(*) from bookmarks however this always returns 0! If I add a where clause for a user such as {{prod}}/api/2.0/search?q=select * from bookmarks where subscriber.id = '5375' it works fine. But I have 500k users so I am don't want to do it that way. The filter by target.type does not work either. I am logged in as Admin user. Any help would be appreciated.Solved227Views1like3CommentsGet bookmarks for other users
Hello, Is it possible with or without the Lithium API to retrieve a list of bookmarks for OTHER USERS, not yourself (or the user you are logged into the API with)? Currently, the API call seems to only support /global/ or /user/self/ parameters, but not /user/id/[user id]. Thank you! :smileyhappy:tester38 months agoAdept101Views0likes1CommentGet bookmarks of other users using API
I have to fetch all the bookmarks in the system. Using V1: http://community.lithium.com/restapi/vc/users/id/30/subscriptions/?restapi.response_format=json Using LiQL: select * from bookmarks Above both method returning the bookmarks of logged-in user only not all the bookmarks even though the logged-in user is Admin in the community. How to get the bookmarks created by all the users in the system?218Views0likes5CommentsCustomise a closed Group Hub page
Hi, I want to customise some Group Hub pages so the same page hosts information/content to non-members, as well as acting as the group hub home for members. e.g. for a product research program, we have a sign-up survey on a page with a whole load of other info designed to promote the program. I've managed to do this with coreNode.id, but it only works for an 'Open' type group hub, and my use case requires it to work on 'Closed' or 'Hidden' group hubs. Code below is just from a quick proof of concept test. <#if coreNode.id??> <#assign node = coreNode.id /> <p>Node: ${node}</p> <#assign query = "SELECT user_context.is_member FROM grouphubs WHERE id = '" + node + "'" /> <#assign x= rest("2.0","/search?q=" + query?url) /> <#if x.data?size gt 0> <#list x.data.items as item> <#if item.user_context.is_member> <p>You're a member</p> <#else> <p>You're not a member</p> </#if> </#list> </#if> </#if> I've tried a couple of other context objects, but the code in my component doesn't seem to display at all on the page if it's closed or hidden. Does anybody have experience of customising group hubs in this way? TIASolvedKev_B8 months agoAdvisor132Views1like2CommentsHow to add Discussion forum Structured Data markup
Discussion forum (DiscussionForumPosting) Structured Data markupon your community's ForumTopicPage "is designed for any forum-style site where people collectively share first-hand perspectives". While for other Structured Data markup it was relatively easy to add a simple JSON linked data given the thread structure with multiple replies creating that would be a bit more complex (basically a query against the messages collection) but what's worse is that it would add much duplication to the page content. That's why I decided to go for the microdata inline markup to enhance the existing topic page with semantic information. Unfortunately, this means that this solution won't be a 100% drag'n'drop deployment for every community as you might need to adapt it a bit to your page structure and class names. The good news is that as long as you are using a skin and theme derived from the Hermes theme some of the elements like authors and title already come with some markup like itemprop="headline" for the title and similar. To complete this markup according to the spec I am running a script that matches certain thread message and author elements and add the necessary attributes. It's probably best if you pick, add and validate each of them one by one using e.g. Google's Rich Results test. Here's the code of my custom component: <#-- This component will add structured markup in form of microdata for ForumTopicPage following Googles Discussion forum (DiscussionForumPosting) structured data definition. See doc at https://developers.google.com/search/docs/appearance/structured-data/discussion-forum --> <@liaAddScript> ;(function($) { $(document).ready(function () { // This should match the outermost container encompassing the whole thread $('.lia-quilt-column-main-content>.lia-quilt-column-alley-left').attr('itemtype', 'https://schema.org/DiscussionForumPosting').attr('itemscope', '').prepend('<meta itemprop="mainEntityOfPage" content="https://community.acme.com'+LITHIUM.CommunityJsonObject.Page.object.viewHref+'" /><meta itemprop="url" content="https://community.acme.com'+LITHIUM.CommunityJsonObject.Page.object.viewHref+'" />'); // Hermes already comes with subject markup that only needs to get changed to 'headline' and publish date added let PublishDate = $('meta[itemprop="dateModified"]').attr('content'); $('.lia-message-subject').attr('itemprop', 'headline').after('<meta itemprop="datePublished" content="'+PublishDate+'" />'); // This goes around all replies in a thread $('.lia-thread-reply').attr('itemprop', 'comment').attr('itemtype', 'https://schema.org/Comment').attr('itemscope', ''); // Marking up all author containers... $('.lia-component-message-view-widget-author-username').attr('itemprop', 'author').attr('itemtype', 'https://schema.org/Person').attr('itemscope', ''); // ...and the author name $('.lia-component-message-view-widget-author-username>.lia-user-name-link>span').attr('itemprop', 'name'); // Marking up the kudo button container as interaction counter... $('.KudosButton').attr('itemprop', 'interactionStatistic').attr('itemtype', 'https://schema.org/InteractionCounter').attr('itemscope', ''); // ...and the kudos count within $('.KudosButton .MessageKudosCount').attr('itemprop', 'userInteractionCount'); // ...and finally define the interaction as like $('.KudosButton .lia-button-image-kudos-label').attr('itemprop', 'interactionType').attr('content', 'https://schema.org/LikeAction'); // These two calls add ImageObject type markup $('.lia-message-image-wrapper').attr('itemtype', 'https://schema.org/ImageObject').attr('itemscope', ''); $('.lia-message-image-wrapper img').attr('itemprop', 'contentUrl'); }); })(LITHIUM.jQuery); </@liaAddScript> Here's a live example topic that you can validate in Rich Results:Solved: Not ALL elements move when I use bold marquee - Graphisoft Community NB: Some warnings get thrown in Google Search Console for anonymous (closed account) authors since they lack the URL and unique name. Bonus: This markup works best if you also deploy theHow to add ProfilePage Structured Data markup Let me know if you have any follow up questions about implementing this and please share any improvements you are building on top.147Views6likes1CommentJavascript fetch vs Freemarker http.client.request issues
I'm having issues with permissions with a Freemarker http.client.reques that works fine as a Javascript fetch. Javascript (returns result as expected): let myHeaders = new Headers(); myHeaders.append( "authorization", "APIKey,apikey_version=2.0" ); myHeaders.append( "content-type", "application/json" ); myHeaders.append( "x-lc-community-host", "community.stage.site" ); let graphql = JSON.stringify({ query: "\nfragment questionFields on Question {\n id\n user{\n id\n displayName\n __typename\n }\n}\n\n\n\nquery post($id: ID!, $lookupColumn: IdType, $lithium: Boolean) {\n post(id: $id, lookupColumn: $lookupColumn, lithium: $lithium) {\n ...questionFields\n __typename\n }\n}\n", variables: {"id":"12345","lookupColumn":"id","preprodStubbing":false} } ); let requestOptions = { method : 'POST', headers : myHeaders, body : graphql, redirect: 'follow' }; fetch( "apisite.com/graphql", requestOptions ) .then( response => response.text() ) .then( result => { console.log(result); } ) .catch( error => console.log( 'error', error ) ); But converting that to an endpoint (controller), I get an error, {'error' : "http request not allowed: http client not allowed: hostname-not-in-allowed-domains-list"} Any ideas why these should result in different results? Am I missing something on the http.client.requestversion? Freemarker code: <#assign articleID = http.request.parameters.name.get("articleID",'1234') /> <#assign graphQLCall = '{ query: "\nfragment questionFields on Question {\n id\n user{\n id\n displayName\n __typename\n }\n}\n\n\n\nquery post($id: ID!, $lookupColumn: IdType, $lithium: Boolean) {\n post(id: $id, lookupColumn: $lookupColumn, lithium: $lithium) {\n ...questionFields\n __typename\n }\n}\n", variables: {"id":"1234","lookupColumn":"id","preprodStubbing":false} }' /> <#assign apiResponse = http.client.request("https","apisite.com","graphql") .header("authorization", "APIKey,apikey_version=2.0" ) .header("content-type", "application/json" ) .header("x-lc-community-host", "community.stage.site") .body(graphQLCall,"application/json") /> <#assign apiResponse = apiResponse.post() /> <#if apiResponse.hasError??> {'error' : "${apiResponse.error.message}"} <#else> ${apiResponse.content!"NO content"} </#if>isxtn8 months agoAdvisor208Views0likes5CommentsPostman Collection for Community Classic?
I was working with someone in Khoros TAC on an API related issue and they were using Postman against our community instance, which is on Classic. The only Postman collection I can find is for Aurora: https://developer.khoros.com/khorosauroradevdocs/docs/postman-collection Where is a similar collection for Classic?phoneboy8 months agoDirector232Views0likes3CommentsFetching an agent's email using it's id
Hi, at our company, we are using khoros' analytics api, in order to fetch data about agent's of our user, who's using khoros as their platform. to achieve this we are using the following endpoint: raw_agent_states at our system, we store the agentDisplayId my question is, is there a way using such id, to fetch the Agent's email at a later time? I would like to avoid to refetch all Agents to find the email of only one Agent.levgour8 months agoContributor167Views0likes3CommentsSend data to third-party API when posting/updating post
Hi, I'm exploring automating the Ideas front-end of our community with the different system our product teams use on the back-end. The first issue I'm attempting to solve - creating an API call when a new idea is posted, or an idea is updated on the community. I think this should flow something like follows: Get the ID when a message is posted/updated (assume I need a POST request) This triggers an endpoint to pull out the message data via GET request and pass relevant information to the third-party API Third-party API receives relevant data and their information is updated I have two sticking points I'm trying to answer currently: What's the best way to trigger something from the post page? Is an additional click event on the 'Submit' button acceptable practice? How do I then get the ID so I can use it in a GET request to get relevant data? (Alternatively - is it better to just grab that data - subject, message body, etc, from the post page?) Appreciate any input or suggestions. I'm quite new to POST requests, I think I understand the basics, but I can't find anything in developer docs that breaks down the steps I'm trying to take. Thanks,Kev_B8 months agoAdvisor128Views0likes2CommentsBulk API in PowerQuery
Hello. I am trying to fetch data with the Bulk API using Power Query (Excel / PowerBI), but I'm facing issues in the identification. I have several options (anonnymous, windows, basic, API web). I tried all of them, but could not connect. I have my Client ID and access token in the Analytics page (I also tried to reset token), but I can't find how to authenticate wih Power Query. How can I do it, please?207Views0likes3CommentsAPI v2 Search doesn't work
Reading this page, I quote: "In v2, perform a one-or-more term search with a comma-separated list of terms wrapped in parentheses. Use this when you want to return messages that have at least one of these terms in the defined fields. WHERE subject MATCHES ('apples', 'bananas', 'cherries')" This query returns 2 results: select subject,body from messages where subject matches 'attachment' This query returns 0 results. select subject,body from messages where subject matches ('attachment','android') According to the documentation I should be getting results. Fair to say that it's not WAI?1KViews0likes9CommentsCan I call a cURL resource in Freemarker component?
Is there a way to call a cURL resource in a Fremarker component? I have a proprietary cURL resource that I want to call in a Freemarker component, that returns JSON. I can't seem to find any reference on how to do this. Is there a way in the Community to do that? Thanksisxtn9 months agoAdvisor198Views0likes4CommentsrestBuilder with search endpoint to return messages with admin privileges?
Hi, When I call <#assign comments = restBuilder().method("POST").path("/search").body(query).admin(true).call()> where <#assign query = { "messages": { "fields": [ "id", "subject", "author.id", "author.first_name", "author.last_name" ], "sorts": [ "post_time DESC" ], "constraints": [ { "parent.id": '${messageId}', "board.id": "${nodeId}" } ], "limit": 20 } }> I'm not getting author.first and last name even while making the call as an admin. The first and last name are only visible if user is an admin or has elevated access, all other users will not see the names. Does anyone know why? Is the admin(boolean) method broken in general or just for the search endpoint? Thanks!djondinium9 months agoExpert132Views1like2CommentsCan I cache a component based on **parameter** ?
I have a component: <component id="example-component" category="foo"/> <component id="example-component" category="bar"/> <component id="example-component" category="baz"/> and I'd like to cache it. <!-- Cache for 60 seconds --> <@liaMarkupCache ttl="60000" variation="node" anonymousOnly="false" /> <!-- Display different HTML based on parameter. Example: --> <#assign category_val = env.context.component.getParameter("category")!"" /> <div>${category_val}</div> But, this results in: foo foo foo But I'd like: foo bar baz It looks like Custom Variations may scratch the itch, but I'm having trouble wrapping my head around ${componentCacheSupport.setCacheVariation("user_id_var", user.id)} Before I go splitting this component up into example_component_foo, example_component_bar, example_component_baz... is there an easier way to cache this? I'd greatly appreciate any tips or pointers!Solvedkeithkelly9 months agoLeader164Views0likes5CommentsPossible to disallow API calls by anonymous users?
Hi team, Wondering if there's a configuration available to disallow API calls by anonymous users. e.g.https://community.[hostname].com/[server]/api/2.0/search?q=SELECT+*+FROM+usersdumps a bunch of data even from an anonymous call. This info is also visible on user profiles (it doesn't expose anything that's not on user profiles already) but it's making some folks on our team a little nervous to have this data available in a big chunk like this. Thanks!Solved145Views1like3CommentsPossible to Cache the Output of an Endpoint?
I have a custom endpoint that returns custom KPIs per board. Custom board lists on the Community Home page. For Board Oversight teams, leadership , etc. I want to post the board-level KPIs (#1) directly on the home page's board lists (#2). Bad (current) way of doing it: Calculate KPI data for each board...each and every time the board list is generated. Can I EITHER: Cache the KPI endpoint response, OR Cache each individual metric as its looked up (cache key would be the board ID)keithkelly9 months agoLeader94Views0likes1CommentDev server best practices?
Hello Khoros devs & techies - We just got budget approval for a dev server, yay! Curious, for those of you who have dev servers as part of your Khoros infrastructure, what are some best practices and/or lessons learned? For example - do you try to keep the configurations in sync between prod, staging, and dev? What processes do you have in place regarding getting dev changes synched onto staging? (I believe this has to be done via a support ticket or the SDK) Thanks for any words of wisdom! - Caroline298Views0likes7CommentsHow to add Event / Occasion Structured Data markup
Event Structured Data markupon your community's OccasionPage in your blog "makes it easier for people to discover and attend events through Google Search results and other Google products, like Google Maps.". Here's some working code to add a simple JSON linked data set to be used on the OccasionPage. Ideally, you would drop this in a custom component which you add to the page layout. Since it's not rendering I would recommend adding it somewhere towards the end of the page, e. g. in the footer. <#-- This component will add structured markup in form of JSON linked data for OccasionPage (Event). See doc at https://developers.google.com/search/docs/appearance/structured-data/event --> <#assign occasionQuery = "SELECT occasion_data.start_time, occasion_data.end_time, occasion_data.status, occasion_data.featured_guests FROM messages WHERE id = '${page.context.thread.topicMessage.uniqueId}'"/> <#assign occasionInfo = rest("2.0", "/search?q=" + occasionQuery?url("UTF-8") + "&restapi.response_style=view").data.items /> <#attempt> <#assign images = (liql('SELECT original_href,width FROM images WHERE messages.id = "${page.context.message.uniqueId}"').data.items) /> <#recover> <#if DEBUG?? && DEBUG> ${query} ${.error} </#if> </#attempt> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Event", "name": "${page.context.message.subject}", "startDate": "${occasionInfo[0].occasion_data.start_time?datetime} GMT${occasionInfo[0].occasion_data.start_time?datetime?string('Z')}", "endDate": "${occasionInfo[0].occasion_data.end_time?datetime} GMT${occasionInfo[0].occasion_data.end_time?datetime?string('Z')}", "eventStatus": "https://schema.org/EventScheduled", "eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode", "location": { "@type": "VirtualLocation", "url": "${page.context.thread.webUi.url}" }, <#if images?? && (images?size gt 0) > <#attempt> "image": "${http.request.serverName}${images[0].original_href}", <#recover> "image": "${http.request.serverName}${asset.get("/html/assets/community-default-image.png")}", </#attempt> </#if> "description": "${page.context.message.bodyRaw}", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD", "availability": "https://schema.org/InStock", "validFrom": "${page.context.message.postDate?datetime} GMT${page.context.message.postDate?datetime?string('Z')}", "url": "${page.context.thread.webUi.url}" }, "organizer": [{ "@type": "Person", "name": "${page.context.thread.topicMessage.author.login}", "url": "${page.context.thread.topicMessage.author.webUi.url}" }] } </script> Some comments: If no image is found with the Event message then a default community placeholder cover image is expected at/html/assets/community-default-image.png I'm assuming all events are virtual ones. If that's not the case for your community you might want to check against occasion_data.is_live_stream Google's markup definition also includes more variants foreventStatus if the event got moved from in person to virtual, cancelled etc. I couldn't find a good equivalent in Khoros Event data so every event is just marked up as EventScheduled (with a future or past start_time) 🙂 Event guests should probably be included in the markup as "performers", but I gave up listing the content of the occasion_data.featured_guests hash. Maybe you can make it work and share back the improved code?75Views2likes0CommentsGet sub categories and group hubs using single API
Hi Team, We are working on a use case where a category has 10 subcategories and 5 group hubs and we want to fetch all the details of the category (both subcategories and group hubs) via a single v2 API. Is there any specific API that is available to get those details? Thanks, Srujana Satya Datla.satya10 months agoExpert114Views1like2CommentsWhat's the Best Practice for showing Badge Count beside Profile Pic on all posts? (Caching?)
A reasonable request from SME's to encourage competition & bragging rights: Display a user's Badge Count beside their name / profile pic. My current prototype feels like a worst practice: <#assign userBadges = rest("/users/id/"+res.author.id+"/badges/?page_size=1000&restapi.response_style=view").user_badges /> <#assign userBadgeCount = userBadges.user_badge?size /> What are some best (or heck, at least less bad) practices for doing something like this? (above, mocked up in a topic list by mistake 😂 ... we'd primarily want to use these within the discussions themselves.)keithkelly10 months agoLeader104Views0likes2Comments- Jk0710 months agoAdept85Views0likes1Comment
- Jk0710 months agoAdept118Views0likes1Comment
How to add structured data
Dear Community, I’d like to add structured data (like schema.org) to our blog articles.Therefore I created a new component and added the code below: <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "BlogPosting", "headline": "${page.context.thread.topicMessage.subject}", "image": { "@type": "ImageObject", "url": "", "height": "", "width": "" } "datePublished": "${page.context.thread.topicMessage.postDate?datetime}", "author": { "@type": "Person", "name": "${page.context.thread.topicMessage.author.login}" } } </script> It’s fine so far, but how can I add more info like image, heigh an width? Are there any other recommendations how to add structured data? Thank you, best regards, clemensw116Views0likes1CommentHow to add Article Page Structured Data markup
Article Structured Data markupin your blog "can help Google understand more about the web page and show bettertitle text, images, anddate informationfor the article in search results on Google Search and other properties (for example, Google News and theGoogle Assistant)". Here's some working code to add a simple JSON linked data set to be used on the BlogArticlePage. Ideally you would drop this in a custom component which you add to that page layout. Since it's not rendering I would recommend adding it somewhere in the footer. <#-- This component will add structured markup in form of JSON linked data for BlogArticlePage. See doc at https://developers.google.com/search/docs/appearance/structured-data/article --> <#attempt> <#assign images = (liql('SELECT original_href,width FROM images WHERE messages.id = "${page.context.message.uniqueId}"').data.items) /> <#recover> </#attempt> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "NewsArticle", "headline": "${page.context.message.subject}", <#if images?? && (images?size gt 0) > <#attempt> "image": "${http.request.serverName}${images[0].original_href}", <#recover> "image": "${http.request.serverName}${asset.get("/html/assets/community-default-image.png")}", </#attempt> </#if> "datePublished": "${page.context.message.postDate?datetime}", "author": [{ "@type": "Person", "name": "${page.context.thread.topicMessage.author.login}", "url": "${page.context.thread.topicMessage.author.webUi.url}" }] } </script> This is a MVP version as it's lacking some details that are part of (but not required) Google's spec: dateModified - Should include the timestamp the blog article was last edited. This is not available via a context object but would require querying the message collection for last_edit_time List of all authors - Currently I'm listing only the initial article author, but no contributors. The author property would be enhanced to something like "author": [{ "@type": "Person", "name": "LauraV", "url": "https://community.khoros.com/t5/user/viewprofilepage/user-id/107047" },{ "@type": "Person", "name": "John D", "url": "https://community.khoros.com/t5/user/viewprofilepage/user-id/27326" }] Please give it a spin, validate everything is working correctly in Google Search Console,Schema Markup Validator, orGoogle's Rich Results Test Tooland be a happier Community Manager / Operations person. Should you happen to improve the above script and add any missing feature please share them back here.68Views1like0CommentsGet All Labels using API v1 call.
How can I get all the labels in the community using the Community API v1 call?SolvedJk0710 months agoAdept187Views0likes4CommentsHow can I increase the "Search Results Paging" indicators? (to show the total # of pages)
When I search & see something like this, I think "oh, there's not much content on XYZ topic" But on other forums, this is an indicator (to me) of the richness of the forum. Seeing [1] [2] [3] ... [75] tells me "Yeah so we've got a whole buncha stuff on that query. Go refine your search criteria to be more sepecific so we can give you more relevant results." What's the level of effort to achieve something like this? I'm open to: Built-in OOTB methods Easy overrides Building a custom component. (pointers appreciated, but I'd like to make sure there's not an easier way first. )keithkelly10 months agoLeader121Views0likes3CommentsIs there any way to get the user data in Page Head Content in JavaScript?
I want to get user data like roles, username, etc in the Page Head Content ( in the wrapper ) and use the data to integrate an analytics tool. The issue is that this user data is fetchable only using Freemarker and freemarker would not work in the header script. Do we know if therei is a way to fetch all this data in a script tag itself? I know one way would be to make an AJAX request to an endpoint and getting all the data from the endpoint's response. But, that would mean making an API call on home page load and might not be good for performance.93Views0likes1CommentHow to add Breadcrumb Structured Data markup
So you want to add Breadcrumb Structured Data markup to your Khoros Community Classic to potentially allow richer search result presentation with added context of where a content piece sits within your structure? That's more easy than you thought. Create a new custom component calledcommon.widget.breadcrumb@override- The@override makes this component replace Khoros core breadcrumb component, so you don't even need to update any layouts including breadcrumb currently. Then drop the following Freemarker code: <#attempt> <#assign depth = 0 /> <div class="BreadCrumb crumb-line lia-breadcrumb lia-component-common-widget-breadcrumb" class="BreadCrumb crumb-line lia-breadcrumb" aria-label="breadcrumbs" role="navigation"> <ul id="list" class="lia-list-standard-inline" itemscope itemtype="http://schema.org/BreadcrumbList"> <#list page.content.nav.breadcrumb.crumbs as crumb> <#assign depth++ /> <#if crumb_has_next> <li class="${crumb.wrapperCss}" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> <a class="lia-link-navigation ${crumb.css!"crumb"}" itemprop="item" href="${crumb.url}"> <span itemprop="name">${crumb.text}</span></a> <meta itemprop="position" content="${depth}" /> </li> <li class="${crumb.separatorCss}" aria-hidden="true"> <span class="separator">${page.content.nav.breadcrumb.seperator}</span> </li> <#else> <#if (page.name == "PostPage" || page.name == "ReplyPage" || page.name == "SearchPage" || page.name == "PrivateNotesPage" || page.name == "ForumTopicPage")> <li class="${crumb.wrapperCss}"> <#outputformat "HTML"> <span class="lia-link-navigation child-thread lia-link-disabled" itemprop="name">${crumb.text?no_esc}</span> </#outputformat> </li> </#if> </#if> </#list> </ul> </div> <#recover> <!-- Breadcrumb load failure --> <@delegate/> </#attempt> And that's it! Validate your new enrichment a few days after deploying in Google Search Console. One comment on the if statement with the list of pages in line 17: Depending on your page layout where the page title is displayed super prominently next to the breadcrumb you might not always have the page title be the last element in the breadcrumb. If you want the page title to be part of the breadcrumb simply add the page.name to this list of pages. As always: Please share back any feedback and improvements you made. Enjoy!66Views3likes0CommentsPrevent Some Subscription Notification Emails
Hi all, I received a request to customize my client's Community to prevent notifications for replies on Idea discussion posts. Initial exploration suggests that I can change the email templates for all notifications, but don't immediately see a way to prevent some of the notifications from sending. I believe this to be a similar request without a solution from last year: https://community.khoros.com/t5/Khoros-Community-Product/Prevent-sending-emails-on-some-badges/m-p/668032 Any ideas? Thanks in advance, Mark156Views0likes4CommentsStyling event attendance buttons
Events have a sliced buttons with the three attendance options. When the user selects one of the option there's only a small byline further down in the attendance list (Bonus question: why is it part of the attendance list? It's not independent of the tabbed attendance navigation but still shown within those tabs): User expectation from most other event tools is that there's feedback on the buttons to convey the user's choice. Here's a mockup of what I would like to see: I was looking at styling the button depending on the user choice, but unfortunately that is not exposed as a class within the path of the button. The class "lia-occasion-rsvp-response-yes/no/maybe" is exposed in a container which is a child of a sibling to the parent of the button wrapper... and I'm not really in a mood to construct such a complex :has() CSS selector. I thought about overriding the component to expose the attendance status, but that won't really work as the component is dynamically updated when the button is clicked without reloading the page. Any ideas on how you would colour the button element depending on user attendance choice?I currently think this most likely will end up as an idea to expose the lia-response class further up in the DOM which will most likely never be actioned since Khoros focus has shifted from Classic to Aurora...52Views0likes0CommentsUpload button disabled but still able to upload
I have created a couple of chat bots on flow.ai and i disabled the upload button. The capabilility to upload is still there and when a user drags a file onto the Bot interface, it send the document or file to googleapis.com temperary bucket. How can I stop the bot allowing uploads?Goonerchris10 months agoContributor42Views0likes0CommentsPassing post_time Date Constraint in JSON
I have done this successfully in a regular LiQL call but no matter what I try when doing this with JSON I get an error like this: An invalid value was passed for the constraint 'post_time' (on the object 'messages'): The value should be a date, but is '2023-10-01T10:04:30-08:00'. Here is my JSON constraint which is then stringified and the API call is made with JavaScript. "constraints": [ { "board.id": boardId, "depth":0, "post_time": { ">=": "2023-10-01T10:04:30-08:00" } }, { "depth":0, "post_time": { "<=": "2023-11-15T10:04:30-08:00" } } ] Please Help!Akenefick10 months agoGenius73Views0likes1Comment2-way SSO connection between Salesforce and Khoros
Hello, For security, we only allow SSO login access to our Community. That said, my Salesforce team has told me that right now we only have a one-way connection between our Salesforce and Khoros in that we use the Khoros Salesforce Connector to pull data from Khoros into Salesforce. However, if we would like to have a two-way connection to be able to send information from Salesforce to Khoros, it seems like we need a non-SSO login to connect to Khoros from Salesforce, at least if want to connect using the Salesforce fields in the attached image. Can you propose another solution? Is there a way for us to connect our Salesforce to Khoros to send information from Salesforce to Khoros (not just the other way around) without using a non-SSO login? Thanks, SuhailSuhail10 months agoContributor115Views0likes1CommentTemplateModel properties/keys
Hello everyone I am trying to see thepage.context.thread.board properties because I did not find anything on the documentation. Basically what I am currently doing is logging this value into console but I gotlithium.eval.velocity.ThreadTemplateModel@7a6fcf85. I have tried with javascript Object.keys function but I am getting the string into an array and no relevant keys/properties. My main goal is to find a way to get whole thread kudos count without using v1 API call. Is there any other way to achieve that? I tried with v2 but is getting the topicMessage count only.288Views0likes7CommentsURL Redirects
Hi Posting under an alt as we're in the process of moving our community to Khoros from A N Other forum provider... Currently we have a couple of friendly URLs community.secretinc.org/mainforum and community.secretinc.org/newideas Ideally we'd like to use these same URLs to make it easier for our customers and marketing teams. Is this possible with Khoros? I've seen some ideas requests for this, but dont have access to all the knowledge base content etc yet... Thanks, ShhhhSolved244Views0likes5CommentsBox.com Security (for file attachments)
Our security team is getting the heebie jeebies about Khoros attachments (potentially containing PII) being stored on box.com. How much of a concern is this? I'm aware Microsoft & other major tech companies use Khoros - how do they handle the security on this front?keithkelly11 months agoLeader169Views0likes2CommentsCommunity API
Main Difference b/w Community API v1 and API v2, and why both the API's are used why can't only one.SolvedJk0711 months agoAdept230Views0likes4Comments