⬇️ Install package: OJS 3.5 — or browse all Releases.
Shows, on the article (and preprint) landing page, the total number of citations and the list of citing works, gathered from Crossref Cited-by, Scopus, Europe PMC and Google Scholar.
Original plugin by Ronny Bölter (
RBoelter/citations), with contributions from Armin Günther and from the Lepidus team (Jhon and Laís). The design, the Crossref/Scopus/Europe PMC integration, the templates, the CSS and the JavaScript are theirs. This branch only carries that work forward to OJS 3.5, which upstream does not target yet — maintained by OJSBR. New features belong upstream first. See Credits & acknowledgements.
| OJS version | Branch | Plugin release |
|---|---|---|
| OJS/OPS 3.5.x | stable-3_5_0 (default) |
3.5.0.2 |
| OJS/OPS 3.4.x | stable-3_4_0 (upstream mirror) |
3.4.0.1 |
Requires PHP 8.2+. Tested on OJS 3.5.0-3 and 3.5.0-5.
- Adds a block to the article page with a counter per source: Crossref Cited-by, Scopus, Europe PMC, plus a link to a Google Scholar search for the DOI.
- Below the counters, lists the citing works — authors, year, title, journal, volume, issue, pages and a link to each citing DOI.
- Counts are fetched by the reader's browser from a plugin endpoint, so the article page itself is not held up waiting on Crossref or Elsevier.
- Deduplicates: a work returned by both Crossref and Scopus is listed once.
- It does not enable Crossref Cited-by for you. The service is not on by default — you must ask Crossref to enable it for your prefix. Until then every article legitimately reports zero.
- Cited-by only returns citations to your own DOIs. Querying a DOI from another member always comes back empty; that is Crossref's behaviour, not a bug here.
- The list can be shorter than the counter. Crossref returns every citing item, but the plugin
renders only
journal_citeandbook_citeentries — conference papers and dissertations count toward the total without appearing in the list. This is upstream behaviour, kept as is.
- A DOI registered on the article — without it the block does not render at all.
- For Crossref: an active membership and the Cited-by service enabled for your prefix. The credentials are the same ones used for depositing.
- For Scopus: an Elsevier API key (free).
- Europe PMC and Google Scholar need no credentials.
- Upload the release package in Settings → Website → Plugins → Upload a new plugin, or copy
the folder to
plugins/generic/citations(do not rename the folder: OJS 3.5 derives the plugin class namespace from the directory name). - Enable Scopus/Crossref Plugin in the plugin list.
- Open its Settings and fill in the credentials.
Where the block appears depends on the theme. It attaches to the
Templates::Article::Detailshook (andTemplates::Preprint::Detailson OPS). A custom theme that never calls that hook will not show anything, and a theme that calls it outside its article card will render the block without the card's styling.
| Field | What it does |
|---|---|
| Source | Crossref, Scopus, or both |
| Scopus API key | Stored, never displayed again |
| Crossref user / password | The same credentials used for depositing |
| Total number of citations | Shows the counters |
| List of citing articles | Shows the list below the counters |
| Google Scholar | Adds a link to a Scholar search for the DOI |
| Europe PMC | Adds the Europe PMC counter and link |
| Block height | Maximum height in pixels; 0 or empty means unlimited |
The counters are fetched by the browser from:
<host>/index.php/<journal>/citations/get?doi=<doi>
It answers a JSONMessage, so the payload lives under content.
Upstream's newest branch is stable-3_4_0, and it does not load on OJS 3.5. This branch is that
branch plus the smallest set of changes needed to run:
The three that actually broke it
PKP\notification\PKPNotificationno longer exists (renamed toPKP\notification\Notification) — the settings form fataled on save.- The
LoadHandlerhook no longer acceptsdefine('HANDLER_CLASS', …):PKPPageRouterin 3.5 throws if that constant is defined. The handler is now injected through$params[3]of the hook's[&$page, &$op, &$sourceFile, &$handler]signature. Without this thecitations/getendpoint is dead. - The global
import()function was removed in 3.5 — the leftoverimport('lib.pkp.classes.linkAction.request.AjaxModal')call fataled the plugin list page.
The rest
- Reads the DOI from
getCurrentPublication()->getDoi()instead ofSubmission::getStoredPubId(), deprecated since 3.2 and only a proxy to the publication. - Guards a null journal context in the template hook and in the handler.
CitationsHandler::loadSettings()no longer passes an array or an empty string tojson_decode()— under PHP 8 the first is aTypeErrorand the second returnsnull, both violating the method'sarrayreturn type.- Initialises
$resultinCitationsHandler::get()(undefined variable when no provider matched). - Replaces a
Monolog\Loggerbuilt with no handlers — every Guzzle failure was being swallowed silently — witherror_log(). - 3.5 house style:
[]array syntax, first-class callables inHook::add(), andHook::CONTINUE/Hook::ABORTinstead of bare booleans. - Locales: added
pt_BR,frandit(PKP 3.5 resolvesfr, notfr_FR), for seven in total.
The processors, templates, CSS and JavaScript are untouched upstream code.
- PHPUnit (
tests/): what the plugin makes of the answers of Crossref and Scopus — the count, the list built only when the journal asked for it, an answer that is not the expected XML or JSON, and the requests it sends, against a mocked HTTP client. Without credentials no request is made at all. - Cypress (
cypress/tests/functional/): enables the plugin, checks that the article page carries the block at most once, that the citations endpoint answers JSON, and that the page comes out untouched while the plugin is off. Nothing is asked of Crossref or Scopus. - Verified on OJS 3.5.0.3.
Tests are kept in the repository and are not part of the release package.
Generative AI (Claude, by Anthropic) was used to write and run tests, improve the code and bring it in line with PKP standards. Every change is reviewed and tested by OJSBR, which is responsible for the published releases.
- Ronny Bölter — author and maintainer of the original
RBoelter/citationsplugin. The whole plugin is his design and his work. - Armin Günther — contributor upstream.
- Lepidus Tecnologia (Jhon and Laís) — contributors upstream.
- Crossref, Elsevier / Scopus, Europe PMC and Google Scholar — the citation data and the logos are theirs; this plugin only queries and displays it.
- Public Knowledge Project, Simon Fraser University and John Willinsky — OJS/OPS and the plugin framework.
- OJSBR — this OJS 3.5 branch and its maintenance.
GNU GPL v3, the same as upstream. See LICENSE and docs/COPYING.
Exibe, na página do artigo, o número total de citações e a lista dos trabalhos que citam, obtidos no Crossref Cited-by, na Scopus, no Europe PMC e no Google Acadêmico.
Este plugin não é da OJSBR. Ele foi criado e é mantido pelo Ronny Bölter (
RBoelter/citations), com contribuições do Armin Günther e da equipe da Lepidus (Jhon e Laís). O desenho, a integração com Crossref/Scopus/Europe PMC, os templates, o CSS e o JavaScript são deles. Esta branch apenas leva esse trabalho adiante para o OJS 3.5, versão que o projeto original ainda não cobre — manutenção da OJSBR. Funcionalidade nova deve ir primeiro para o repositório original.
- Um contador por fonte na página do artigo: Crossref Cited-by, Scopus, Europe PMC e um link para a busca no Google Acadêmico pelo DOI.
- Abaixo dos contadores, a lista dos trabalhos que citam — autores, ano, título, periódico, volume, número, páginas e o link para o DOI de cada um.
- Os números são buscados pelo navegador do leitor num endpoint do plugin, então a página do artigo não fica esperando a Crossref nem a Elsevier responderem.
- Um trabalho que aparece na Crossref e na Scopus é listado uma vez só.
- Não habilita o Cited-by para você. O serviço não vem ligado: é preciso pedir à Crossref a habilitação para o seu prefixo. Enquanto isso não acontece, todo artigo devolve zero — e está certo.
- O Cited-by só devolve citações aos DOIs do próprio membro. Consultar o DOI de outra revista sempre volta vazio; é o comportamento da Crossref, não um defeito daqui.
- A lista pode ser menor que o contador. A Crossref devolve todos os itens citantes, mas o
plugin monta a lista só com
journal_citeebook_cite— anais e teses entram no total sem aparecer na lista. É comportamento do original, mantido como está.
- DOI cadastrado no artigo — sem DOI o bloco nem aparece.
- Crossref: associação ativa e o Cited-by habilitado para o seu prefixo. A credencial é a mesma usada no depósito.
- Scopus: uma chave de API da Elsevier (gratuita).
- Europe PMC e Google Acadêmico não pedem credencial.
- Envie o pacote em Configurações → Website → Plugins → Enviar um novo plugin, ou copie a
pasta para
plugins/generic/citations(não renomeie a pasta: o OJS 3.5 deriva o namespace da classe do nome do diretório). - Habilite o Plugin Scopus/Crossref na lista.
- Abra as Configurações dele e preencha as credenciais.
Onde o bloco aparece depende do tema. Ele se pendura no hook
Templates::Article::Details(e noTemplates::Preprint::Details, no OPS). Tema próprio que não chama esse hook não exibe nada; tema que chama fora do cartão do artigo exibe o bloco sem o estilo do cartão.
A branch mais nova do original é a stable-3_4_0 e ela não carrega no OJS 3.5. As três quebras
reais foram:
PKPNotificationdeixou de existir no 3.5 (virouNotification) — o formulário de configuração dava fatal ao salvar.- O
PKPPageRouterdo 3.5 lança exceção se a constanteHANDLER_CLASSestiver definida; o handler agora entra pelo$params[3]do hookLoadHandler. Sem isso o endpointcitations/getfica morto. - A função global
import()foi removida no 3.5 — a chamada remanescente derrubava a página de plugins.
As demais mudanças (DOI lido da publicação, guardas de contexto nulo, json_decode() que era
TypeError no PHP 8, logger sem handler que engolia todo erro do Guzzle, estilo do 3.5 e os
locales novos) estão detalhadas na seção em inglês acima. Os processadores, os templates, o CSS e
o JavaScript são código original, intocado.
- PHPUnit (
tests/): o que o plugin faz das respostas da Crossref e da Scopus — a contagem, a lista montada só quando a revista pediu, uma resposta que não é o XML ou o JSON esperado, e as requisições que ele envia, contra um cliente HTTP simulado. Sem credenciais, nenhuma requisição é feita. - Cypress (
cypress/tests/functional/): liga o plugin, confere que a página do artigo traz o bloco no máximo uma vez, que o endpoint responde JSON e que a página sai intacta com o plugin desligado. Nada é pedido à Crossref nem à Scopus. - Verificado no OJS 3.5.0.3.
Os testes ficam no repositório e não fazem parte do pacote da release.
Foi usada IA generativa (Claude, da Anthropic) para escrever e rodar testes, melhorar o código e alinhá-lo aos padrões da PKP. Toda mudança é revisada e testada pela OJSBR, que responde pelas releases publicadas.
de, en, es, fr, it, pt, pt_BR.
GNU GPL v3, a mesma do original. Veja o LICENSE e o docs/COPYING.