Skip to main content
Surfer’s JavaScript library hands you the panel as an iframe to place and size yourself, and the panel scores every change you send it. The panel shows one Content Editor, the document Surfer builds around your target keywords, holding the guidelines and the Content Score (The guidelines panel).

Availability

To embed Surfer in your CMS, contact [email protected]. The embed itself needs:
  • Your editor runs in a browser, on an HTTPS page. The panel’s request for storage access is refused on a page that is not served over HTTPS.
  • The writer is signed in to Surfer in the same browser, to link or create a Content Editor from the panel. A page whose permalink already resolves shows its guidelines either way (Access and sharing).
  • The browser lets Surfer use its cookies inside your page: third-party cookies allowed for app.surferseo.com, or storage access granted when the panel asks. No browser extension is needed; Sign in and cookies has the details.
  • The writer’s Surfer account includes Content Editors.

Add the library

Paste this loader into the <body> of your page, before your own script. It defines window.surferGuidelines at once and fetches the library in the background:
A call to init or initWithOptions made before the library arrives is replayed once it has loaded. A stored setHtml is sent by init, not by the load itself. A host that uses initWithOptions sends its HTML through the handle instead, as the example below does.
initWithOptions returns its handle only once the library has loaded; before that, the loader’s stand-in returns nothing. The example below therefore runs on the page’s load event, which the browser holds until the script has run.
surfer_guidelines_1_x_x.js is the current release. Versioning covers pinned files and what a pin freezes. The WordPress plugin, the Contentful app, and the Surfer for Google Docs extension use the same library.

Add a container and start the panel

Give the panel an element to live in, then create it with initWithOptions, set the permalink, and send the editor’s HTML. The permalink in the example is a placeholder. A page URL anyone can guess is a permalink anyone can guess, so read Access and sharing before you settle on its format. Add this after the loader. It has a text area for the article’s HTML and a container for the panel:
What each call does:
  • initWithOptions creates the iframe and returns it together with the functions that drive it. The iframe is not in the page until you append it.
  • partner names your integration to Surfer. Use one short identifier for your product.
  • setPermalink tells the panel which document this is; until it receives one, the panel stays on its loading state.
  • setHtml sends the article. Call it once at start and again on every change.
  • onContentScoreChanged runs each time the SEO score changes.
The library sets no size and injects no CSS, so style the iframe yourself. Surfer’s Google Docs panel uses a sidebar 320 to 400 pixels wide. This CSS, in your page’s stylesheet, puts the panel at the right edge, full height:

What you see

The panel shows one of four things, depending on whether the permalink resolves and whether the writer is signed in. Picking or creating a Content Editor in the dashboard links it to the permalink (Credits covers what that costs). From then on the panel shows its guidelines, and every later visit with the same permalink finds it. What the panel shows covers the tabs and controls.

Send the article’s HTML

Send the article body as HTML, on every change, and read the score back from the callback.
  • When: once at start and after each edit. Each call posts the whole HTML to the panel, so debounce the call if your editor fires on every keystroke.
  • After setPermalink: call setHtml again, because a new permalink drops the HTML the library holds (The handle).
Use onContentScoreChanged to receive scores. The JavaScript API documents its payload, the zero-score behavior, and the other callbacks.

Next steps

  • Access and sharing: the signed-in and shared modes, getting a permalink for an existing Content Editor from the API, and sharing tokens.
  • JavaScript API: every option, callback, and handle function with its payload.

Troubleshooting

The symptoms below trace to cookies, the permalink, the HTML feed, or the subscription.
The browser blocks third-party cookies on your page, so the panel cannot read the writer’s Surfer session. The screen offers a way to grant access. The connect screen has its controls and the steps.A private or Incognito window that blocks third-party cookies shows the same screen.
The permalink did not resolve.
  • A value that differs by one character from the one the Content Editor was linked with is a different permalink.
  • A changed sharing token also makes a different permalink.
  • onDraftLoaded receives null when the permalink does not resolve.
A panel that never leaves the loading indicator has received no permalink at all. Access and sharing covers linking an existing Content Editor and keeping tokens stable.
The panel sends a score only when it has HTML and the score is above zero. Check that:
  • setHtml receives a string of HTML, not your editor’s document object.
  • It runs again after every change and after each setPermalink.
  • The text is not empty.
Timing is not the cause. The library holds HTML sent early and delivers it once the panel has loaded the Content Editor (The handle).
An organization’s subscription is not active. Plans has the full message and says which organization it refers to.