ACM Sidebar Integration
10min
Integration
Include the following Scripts
HTML
|
<!-- ACM Scripts --> <script type="text/javascript" src="https://acm.sprylab.com/static/setup/config.js"></script> <script type="text/javascript" src="https://acm.sprylab.com/static/setup/acmInit.js"></script>
Run the acmService.init function
We Currently only provide a bridge for WordPress Gutenberg (if you have your own CMS, please see below)
JS
|
var acmLoginToken = getACMLoginToken(); var initConfiguration = { apiToken: acmLoginToken, // optional bridgeSrc: 'https://acm.sprylab.com/static/setup/wpGutenbergBridge.js' }; window.acmServices.init(initConfiguration);
getACMLoginToken()
This function that can be implemented to authenticate with ACM. It could look like the following:
JS
|
async function getACMLoginToken() { var response = await fetch('https://acm.sprylab.com/core/users/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: '', password: '' }) }); return response.json(); // parses JSON response into native JavaScript objects } var acmLoginToken = await getACMLoginToken().token;
Add the Sidebar IFrame
min-height: So when not authorized, the Login Page is fully visible
width: The sidebar was built for WordPress mainly, which uses per default 280px
HTML
|
<!-- ACM Sidebar Container --> <iframe id="acmSidebar_iframe" src="https://acm.sprylab.com/sidebar" style="min-height: 300px !important; width: 280px !important" />
Keywords
JS
|
var topics = window.acmBridge.getTopicSelection(); // string[] var keywords = window.acmBridge.getKeywordSelection(); // string[] var sidebarSrc = document.getElementById('acmSidebar_iframe').getAttribute('src'); sidebarContainer.setAttribute('src', `${sidebarSrc}?topics=${topics}&keywords=${keywords}`);
Creating your own bridge
When creating your own bridge, you need to modify the initConfiguration
JS
|
var initConfiguration = { bridgeSrc: 'URL_TO_BRIDGE_JAVASCRIPT_FILE' };
The Bridge should look like the following
TypeScript
|
export interface AcmBridge { /** * initialization method of the bridge. This method is called once the authentication is finished. * Any setup tasks which are required for your bridge two work should happen here. This will most likely include * subscribing to events fired by your editor (e.g. when the content is changed or saved) * The configuration object can be extended as desired if you need to pass additional information * * @param config the configuration object used an acmServices.init */ init: (config: BridgeConfiguration) => void, /** * this method will be called whenever the acm widgets request the content of the editor * Additionally, you should call this method whenever your content has changed. * By default, calling this methods triggers a new analysis in the acm widgets (silent = false). * This may not always be desired because of possible subsequent performance and ux issues. * Therefore it is recommended to call this method with silent set to true for minor or informative changes. * It is also recommended to debounce these calls (e.g. one call per second). * * This method is required to send a window message via window.postMessage to the acm widgets iframes. * It is recommended to use acmServices.sendArticleTextChange(article, silent, target) for this purpose. * The first parameter needs to be of type {@link Article} and is required. The silent parameter (see above) * needs to be passed on (can be omitted if false). An optional third parameter can be used to send the message * exclusively to one ACM widget. If this is the case, the contentWindow object of this widget frame * needs to be passed. However this is only an option if you are using multiple ACM widgets. * * @param {boolean} silent silent content update. Should be used for notify-only updates which are not supposed * to trigger immediate updates of the ACM analysis tasks * @param {Element} target optional target frame to exclusively process the update to. * If this is not set, the message should be sent to all frames which were initially configured */ sendEditorState: (silent: boolean, target?: Element) => void, /** * This method is called whenever the ACM Widgets have processed the content and altered the editors content. * In most cases this will be added markup, e.g. an additional ACM-specific Tag with an Id * The article Object passed should be used to update the CMS editor * * @param {ArticleTextState} article the updated article */ editArticleTextState: (article: ArticleTextState) => void, /** * This method is called whenever the ACM Widgets have processed the content and updated / added new data. * This usually contains additional information to the markup added by {@link editArticleTextState} * * @param {ArticleDataState} articleData the articleData */ editArticleDataState: (articleData: ArticleDataState) => void /** * @deprecated Please use redirectToEditorWithURL: (topicIds?: string[], keywords?: string[]) => void * This method is called when an ACM Widget urges the CMS to display the content editor, e.g. there is a * "write article" button in the Topic Selection widget. * * @param {string[]} topicIds topicIds to initialize the editor with. Should be passed to the editor in a way * so the ACM widgets displayed with the editor can access them (e.g. Query Params). optional * @param {string[]} keywords keywords to initialize the editor with. Should be passed to the editor in a way * so the ACM widgets displayed with the editor can access them (e.g. Query Params). optional */ redirectToEditor: (topicIds?: string[], keywords?: string[]) => void /** * This method is called when an ACM Widget urges the CMS to display the content editor, e.g. there is a * "write article" button in the Topic Selection widget. * * @param {string} baseURL the base URL for the link i.e. https://www.wordpress.org/test * @param {string[]} topicIds topicIds to initialize the editor with. Should be passed to the editor in a way * so the ACM widgets displayed with the editor can access them (e.g. Query Params). optional * @param {string[]} keywords keywords to initialize the editor with. Should be passed to the editor in a way * so the ACM widgets displayed with the editor can access them (e.g. Query Params). optional */ redirectToEditorWithURL: (baseURL: string, topicIds?: string[], keywords?: string[]) => void /** * This method is called when an ACM Widget urges the CMS to reload the content editor, e. g. editor text was * altered by the acm backend and saved to your CMS for example after saving links via the ACM Link Optimizer */ reloadEditor: () => void /** * This method is called when loading ACM Widgets next to the CMS Editor. Topic Ids which may have been passed * to the editor in {@link redirectToEditor} or may be present in the article meta data are passed to the ACM Widgets * in this process. This method is used to retrieve the topic ids. * * @returns {string} comma separated list of topic ids */ getTopicSelection: () => string /** * This method is called when loading ACM Widgets next to the CMS Editor. Keywords which may have been passed * to the editor in {@link redirectToEditor} or may be present in the article meta data are passed to the ACM Widgets * in this process. This method is used to retrieve the keywords. * * @returns {string} comma separated list of topic ids */ getKeywordSelection: () => string } Interfaces interface BridgeConfiguration { /** * API Token for ACM usage */ apiToken: string, /** * Array of Target containers in your DOM where the ACM Widgets will be loaded * Make sure these Elements are inside the DOM when this configuration is passed to acmServices.init() */ targetDivs: { /** * name of the ACM component to load as a widget, e.g. 'sidebar' */ component: string, /** * id of the DOM element which will hold the ACM Widget */ target: string }[], /** * The source location of the bridge script implementation */ bridgeSrc: string } interface ArticleTextState { article: EditorStateArticle silent?: boolean } interface ArticleDataState { /** * link recommendation metadata */ links?: LinkRecommendationResponse[] /** * Image analysis metadata */ images?: ImageAnalysis[] /** * Product recommendation metadata */ products?: AmazonProductRecommendationsResponse[] /** * keyword metadata */ entities?: EntityResponse[] /** * should the update be silent */ silent?: boolean } interface EditorStateArticle { /** * The id of the article */ article_id: string /** * Title of the article */ title: string /** * URL of the article in the CMS. optional */ link: string /** * Raw content of the article (just text, no markup) */ rawContent: string /** * Array of block elements representing the article. optional */ structuredContent: { /** * original Content of the block */ originalContent: string }[] /** * HTML Content of the article */ htmlContent?: string /** * The date when it was published */ published?: string } interface LinkRecommendationResponse { articles: ArticleScoreResponse[] badges: { most_recent: number best_retention_time: number most_similar: number } id: string index_paragraph: number keyword: string profile: LinkRecommendationProfileResponse link_parameters: LinkParametersBody occurrence_in_paragraph: number score: number score_articles: number score_length: number score_selection_to_source: number selected_article_id: string status: string text_selection: string } export interface ArticleScoreResponse { id: string title: string overhead: string description: string author?: string ressort?: string type?: string sub_type?: string region?: string premium: boolean reading_time?: number categories: string[] keywords: string[] link: string link_content?: string published?: string image_url: string source: { id: string title: string href: string } provider: ArticleProvider suggested_by: string[] content: string score: number score_retention_time: number score_selection_to_target: number score_paragraph_to_target: number score_source_to_target: number score_recency: number } enum ArticleProvider { CMS = "CMS", NEWS = "news", WP = "WordPress", // deprecated GOOGLE_NEWS = "Google News", // deprecated - wird zu News FEEDLY = "FEEDLY", // deprecated - wird zu News NEWS_API = "News API", // deprecated - wird zu News } interface LinkRecommendationProfileResponse { name: string article_parameters: ArticleParametersBody link_parameters: LinkParametersBody } interface ArticleParametersBody { avg_links_per_paragraph: number preferred_selection_length: number selection_length_weight: number articles_per_selection: number selection_to_source_weight: number } interface LinkParametersBody { date_range: number date_weight: number selection_to_target_weight: number paragraph_to_target_weight: number source_to_target_weight: number categories: string[] categories_weight: number } export interface EntityResponse { name: string types: string[] | null trend_score?: number start_char: number end_char: number wiki_link: string | null confidence: number | null matched_token: string synonyms: Synonym[] } export interface Synonym { synonym: string trend_score: number }
Updated 03 Mar 2023
Did this page help you?
Yes
No