Um dos problemas mais comuns que encontramos em websites, especialmente quando o site é um ecommerce, é o uso de parâmetros para escrever URLs, que por sua vez fazem carregar conteúdos diferentes nas páginas do site. O uso de parâmetros em si nem é um problema, é até uma solução prática, pois oferece agilidade quando o programador utiliza um template para carregar diferentes conteúdos, como as páginas de listagem de produtos em um ecommerce.
Mas essa vantagem da agilidade traz consigo uma desvantagem que pode impactar o site: a abertura para ocorrência de conteúdo duplicado, algo que URLs amigáveis/estáticas geralmente evitam. Isso porque, em URLs e tratamento de parâmetros do lado de servidores de websites, pouco importa a ordem dos parâmetros, mas para Search Engines, faz toda diferença.
Servidores e Search Engines
Quando um servidor recebe uma requisição para acesso a uma URL parametrizada, pouco importa a ordem dos parâmetros na URL:
- www.ecommerce.com/?cat=32&prod=100
- www.ecommerce.com/?prod=100&cat=32
O servidor vai processar e retornar a mesma informação: o produto 100 da categoria 32. Já uma Search Engine parte do princípio de que cada URL encontrada na Internet é um conteúdo distinto de qualquer outro. Esse tratamento “cego” feito por Search Engines tem suas vantagens para o seu desempenho, embora seja óbvio, do ponto de vista de uma pessoa, que as duas URLs vão trazer a mesma informação, há uma queda de desempenho quando se passa a testar se a URL encontrada pode ser igual a outra ou não.
Outro detalhe é que para dois parâmetros a visualização é simples, o teste é simples. Mas para 3 parâmetros, 4, etc., a complexidade, opções e tempo necessário para testes passam a ficar grande demais para valer a pena a queda de desempenho, pois isso implica inclusive em ficar fazendo diversas requisições ao servidor, que pode não aguentar a carga, recusar responder, bloquear requisições, etc.
Para o bem de todos, parece que o melhor caso é realmente entregar ao webmaster a responsabilidade de criar um website consistente, enquanto a Search Engine tenta evitar ao máximo problemas com conteúdo duplicado. Tipicamente as Search Engines oferecem o Canonical Link Element como paliativo para o problema de conteúdo duplicado, ou, a medida em que vai encontrando conteúdo duplicado, vai abandonando a execução de rastreamento do site, pois ele não está acrescentando nada e o processo está sendo uma completa perda de tempo.
URLs com Parâmetros e URLs Amigáveis
Ao se falar em URLs amigáveis, a primeira coisa que vem a mente é o uso de palavras-chave no lugar de números nas URLs de um website. Realmente, em termos bem simples, uma URL amigável caminha por esses lados e, com essa idéia incompleta, acabaram surgindo as URLs amigas da onça, paliativas também, que melhoram o quadro, mas não resolvem a questão:
- www.ecommerce.com/?cat=informatica&prod=mousepad2011
Embora a URL contenha keywords, ela ainda está amarrada a parâmetros que podem ser utilizados em qualquer ordem, gerando diversas URLs distintas, mas que vão carregar o mesmo conteúdo. Em muitos websites, observa-se medidas como utilizar vírgulas ou sinal de adição (+) para tentar tornar a URL mais simples e óbvia, mas que acaba girando em torno do mesmo problema.
Nos idos de 2007, eu escrevi um artigo sobre a otimização e criação de URLs Amigáveis, levantando pontos importantes a se considerar no tratamento de URLs:
- Devem ser curtas (tanto quanto fizer sentido)
- Descrever o conteúdo da página
- Estáticas
- Usar keywords
- Separar palavras por hífen ( – )
- Bijeção
Sobre a bijeção:
Lembrou das aulas de matemática? Pois então, cada URL deve endereçar somente um conteúdo e cada conteúdo deve ser indexado somente por uma URL! Não faz sentido ter duas URLs endereçando o mesmo conteúdo. Naturalmente, isso vai gerar um desconforto para um usuário, que ao digitar diferentes endereços, recebe o mesmo conteúdo. Para não falar que isso será visto como conteúdo duplicado pelos motores de busca.
E sobre serem estáticas, é simplesmente a indicação de evitar URLs com parâmetros. O desenvolvedor do site deve utilizar URLs “dinamicamente estáticas” ou “estaticamente dinâmicas”, como preferir. Ou seja, para Search Engines e usuários, as URLs serão amigáveis: estáticas, com palavras e tudo o mais. Já o servidor fica com o trabalho de, ao receber uma requisição de uma URL estática, tratá-la da maneira correta e responder com um conteúdo dinâmico ou não. Ao receber:
- www.ecommerce.com/informatica/mousepad2011
Responder com
- www.ecommerce.com/?cat=informatica&prod=mousepad2011
De maneira transparente para usuários e Search Engines, ou seja, eles somente conhecerão as versões estáticas de URLs. Também nos idos de 2007, o Celso Fernandes publicou aqui na Agência Mestre o artigo Utilizando mod_rewrite para criar URLs amigáveis, explicando como configurar essa transparência em servidores Apache.
Basta seguir o artigo, configurar as URLs amigáveis com mod_rewrite e problema resolvido, certo? Quase.
Redirecionamento 301, .htaccess e RewriteCond
Na maioria dos casos, provavelmente, o Google já teria várias URLs com parâmetros em seu índice (inclusive as versões duplicadas) de websites assim. Muito provavelmente, também, essas URLs parametrizadas já teriam recebido links externos diversificados e adquirido relevância e rankings em resultados de busca e, independente da quantidade/qualidade, isso não deve ser simplesmente jogado fora.
E para manter os resultados já obtidos com URLs parametrizadas após a troca para URLs amigáveis, é necessário fazer o redirecionamento 301 de cada URL com parâmetros para a sua respectiva URL amigável, ponto-a-ponto, e não todas para a página inicial ou coisa do tipo. Ou seja:
- produto.php?marca=apple para /apple
- produto.php?marca=apple&prod=macbook-pro para /apple/macbook-pro
E assim por diante. Em servidores Apache, é possível configurar esses redirecionamentos utilizando o RewriteCond no .htaccess:
RewriteCond %{QUERY_STRING} !=""
RewriteCond %{QUERY_STRING} ^marca=([0-9-a-z\-]+)&prod=([0-9-a-z\-]+)$ [NC]
RewriteRule ^produto.php(.*)$ http://www.ecommerce.com/%1/%2? [R=301,L]
A primeira linha aplica a condição de que a query string (os parâmetros) não está vazia. A segunda, estabelece uma condição: Se a URL requisitada contiver o parâmetro marca com valor alfa-numérico podendo conter hífen, então ele aplica a linha 3: redireciona para www.ecommerce.com/(valor encontrado no parâmetro marca)/(valor encontrado em prod) – precisamente o efeito desejado:
- Na requisição de uma URL produto.php?marca=apple&prod=macbook-pro-2011
- O servidor redireciona o usuário com código HTTP 301 para
- http://www.ecommerce.com/apple/macbook-pro-2011
Observe como os valores capturados entre parenteses na linha 2 são acessados na linha 3 com o uso do símbolo % seguido de um número (que é referente a ordem dos parenteses – primeiro, segundo, …).
Considerações Finais
É importante ter conhecimento de expressões regulares para facilitar todo o processo. Nas linhas do .htaccess apresentadas anteriormente, a segunda linha contém uma expressão regular, utilizada duas vezes, para capturar combinações de letras e números de forma mais eficiente do que escrever uma a uma.
Aqui na Agência Mestre, a Fabiane Lima escreveu um guia de introdução para expressões regulares que pode ser de bastante ajuda neste tipo de configuração. Outra ajuda interessante é a ferramenta .htaccess tester: htaccess.madewithlove.be – embora ela não responda perfeitamente como um servidor rodando o .htaccess, ela é bem útil.
Outro ponto importante para se ter atenção é que o .htaccess funciona totalmente ao pé-da-letra, ou seja, na minha regra acima, se um dos dois parâmetros estiver ausente da URL, ou se eles estiverem em ordem invertida, o redirecionamento não será feito. Você como desenvolvedor deve entender o seu próprio sistema e providenciar as soluções.
A ajuda vem com o uso de condicional por expressão regular ou outras funções do .htaccess:
- Aparecer ou não o segundo parâmetro controlado por expressão regular
RewriteCond %{QUERY_STRING} !=""
RewriteCond %{QUERY_STRING} ^marca=([0-9-a-z\-]+)(&prod=([0-9-a-z\-]+))?$ [NC]
RewriteRule ^produto.php(.*)$ http://www.ecommerce.com/%1/%2? [R=301,L]
- Aparecer ou não o segundo parâmetro usando OR
RewriteCond %{QUERY_STRING} !=""
RewriteCond %{QUERY_STRING} ^marca=([0-9-a-z\-]+)&prod=([0-9-a-z\-]+)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^marca=([0-9-a-z\-]+)$ [NC]
RewriteRule ^produto.php(.*)$ http://www.ecommerce.com/%1/%2? [R=301,L]
- Ordenar parâmetros
RewriteCond %{QUERY_STRING} !=""
RewriteCond %{QUERY_STRING} ^prod=([0-9-a-z\-]+)&marca=([0-9-a-z\-]+)$ [NC]
RewriteRule ^produto.php(.*)$ http://www.ecommerce.com/%2/%1? [R=301,L]
Entre outras peculiaridades que cada sistema pode ter e que é dever do desenvolvedor estudar e cobrir os possíveis casos.
Espero que o artigo tenha sido proveitoso e que ajude a orientar na direção da solução para o redirecionamento 301 de URLs com parâmetros, para URLs sem parâmetros utilizando .htaccess.
Grande Frank,
Esse artigo é muito bom, dá um exemplo prático de redirecionamento com .htaccess que muita gente não sabia, mas que é extremamente importante.
Parabéns pelo artigo, eu mesmo já usei esse redirecionamento com as suas dicas e funcionou perfeitamente.
Abraços!
Você acabou fazendo um post sobre a pergunta que lhe fiz no twitter!? vlw Rei! 😉
@keycodebr
Olá Frank…
Mais no caso de redir 301, se usar a canonica, não daria na mesma? Assim aos poucos vai indexando a nova e ganhando relevancia….ou continuaria aparecendo como duplicada?
Abs
O 301 é uma regra da qual o Google não consegue fugir. O canonical fica sujeito ao Google fazer essa compensação de que uma página é a outra.
É melhor usar o 301 no caso que eu exemplifiquei acima. O canonical funciona também, porém de forma mais lenta…
Olá Frank,
eu não conhecia ainda a RewriteCond %{QUERY_STRING} bem bacana o uso dela ajudará muito.
Obrigado e belo post.
Ótimo artigo. Parabéns Frank.
Sempre bom artigos assim com exemplos práticos.
Abraço
Nossa muito bom o artigo.
Além de bem redigido, muito bem explicativo…
Valeu!!!
Olá Frank,
Tentei aplicar esta regra em um site .NET (com extensão ASPX). Como a estrutura dos links em ASPX são diferentes, tive dificuldade em converter.
Precisava o link http://www.noicla.com.br/mostraartigo.aspx?2,false seja visto como http://www.noicla.com.br/artigo/2.
Tentei usar assim:
RewriteCond %{QUERY_STRING} !=””
RewriteCond %{QUERY_STRING} ^mostraartigo.aspx?([0-9]+) [NC]
RewriteRule ^mostraartigo.aspx?(.*)$ artigo/%1 [R=301,L]
Mas não funcionou.
Onde errei?
Murilo.
Murilo, asp não é minha especialidade, mas a julgar pelo seu uso da informação na query string do .htaccess, eu imagino que ali esteja o erro.
Tente:
RewriteCond %{QUERY_STRING} !=””
RewriteCond %{QUERY_STRING} ^([0-9]+)$ [NC]
RewriteRule ^mostrartigo.aspx(.*)$ http://www.noicla.com.br/artigo/%1? [R=301,L]
Se der certo, nos avise por aqui!
Olá Frank, uso um código bem parecido com esse teu código e até que deu certo pra mim porque já uso url amigaveis, porém se jogar um link com duas palavras passando direto pelo parâmetro o código já não redireciona. Sabe me dizer qual é o motivo? Abraço
Olá Frank,
Obrigado pelo auxílio.
Tivemos evolução. Com estas configurações ao clicar em um link que tem o formato original http://www.noicla.com.br/mostraartigo.aspx?2,false, é redirecionado para o link http://www.noicla.com.br/artigo/2.
Só que então dá mensagem de que esta última página não existe…
Devo criar um tratamento via programação para isto?
Neste caso, desculpe minha ignorância, mas pensei que o .htaccess resolveria tudo, e não é o que ocorreu.
Murilo.
Bom, acho que você poderia estudar um pouco mais sobre o .htaccess, pois ele pode resolver a página retornando o conteúdo /mostraartigo.aspx?2,false sem trocar a URL correta /artigo/2; ou você pode resolver por programação também – aqui já entra a parte que eu não tenho conhecimento específico: ASP.
Quando tentei aplicar urls amigáveis ao meu site, fiz o redirecionamento 301, mas tá dando erro 404, ele redireciona certinho mas dá o erro 404.
Olá Jonathan, se o servidor está respondendo erro 404, então o redirecionamento não está correto. Se você usa algum CMS (WordPress, Joomla, …), tente procurar ajuda específica. Eu já vi o WordPress dando algum trabalho em cima disso em virtude das suas funções padrão (wp_head, get_header, …).
Pra mim tudo funcionou perfeitamente bem ,só que acho que fiz algo errado pq a página está entrando em loop infinito, eu estou tentando fazer com que a página colunas.php?colunista=33 redirecione para colunas/33/nome-da-materia, só que sempre entra em loop, ou seja o redirecionamento está ok, mas não para nunca de redicerionar, porque a página é a mesma, só que eu não quero que ela seja acessada pelo colunas.php, mas somente pelo colunas/33/nome-da-materia, alguma ideia de como parar o loop?
Samuel, imagino que você esteja fazendo as URLs colunas/XX/nome-da-materia chamarem o colunas.php denovo, colunas.php?colunista=XX.
Se esse for o caso, vai realmente resultar em looping.
Se esse for o caso, copie o colunas.php e dê um novo nome a ele (colunas2.php); chame esse novo arquivo no lugar.
Sem o código em mãos, imagino que esse seja o caso. Boa sorte!
Era isso mesmo que eu estava fazendo, a página se “re-chamava” [nossa, inventei uma palavra], mas ai acabou caindo naquele loop, ai eu fiz uma outra página idêntica e redirecionei, agora está funcionando perfeitamente!
Estou com a seguinte situação:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^?]*) index.php?_rota_=$1 [L,QSA]
Certamente, se eu tentar acessar uma imagem em http://www.meu_site.com/imagens/produto1.jpg direto eu não consigo.
Como manter essa regra como está e permitir o acesso as imagens de /imagens ?
Você pode adicionar uma regra antes da sua última linha sobre o /imagens como [L] (last/última) e aí a regra com o index.php não será acionada.
Bom dia Frank, tudo jóia? Cara estou iniciando nesse mundo de SEO e em breve estarei realizando o curso com vocês, com certeza. Me tire uma dúvida, por gentileza. Montei um site, as URL’s estavam relativamente boas e ficaram em uma posição legal no início, mas eu queria melhorar, simplesmente apaguei e montei outras url’s, com o mesmo conteúdo e com algumas melhoras nas descriptions e em conteúdos únicos. A posição caiu bruscamente, e desde então não consigo reavivar. Sei que existe o procedimento de redirecionamento 301, provavelmente deu problema de duplicidade, mas já nem lembro mais as primeiras URL’s que fiz. Como proceder nesses casos? Abraço e obrigado desde já.
Jefferson, você precisa identificar todas alterações feitas, tentar identificar aquela(s) que tenha(m) tido problema(s) e corrigir da melhor maneira possível.
Corrigido, é seguir em frente com a otimização do site.
Estou tentando usar esse redirecionamento, mas não está funcionando… O navegador diz que ele está em loop. O que poderia ser?
Pode ser precisamente o que o navegador está reportando: o loop.
As suas linhas no .htaccess estão fazendo com ele se repita indefinidamente.
Eu acabei não citando no artigo mas a letra L que aparece nos códigos, logo após o R=301, é indicativo de “final de verificação de regras” – L = Last; ou seja, após executar aquela linha, retorna o resultado e finalize a execução.
Dependendo do caso, esse L pode te ajudar.
Dependendo do caso, é questão de reescrever o código mesmo. Veja a dúvida do Samuel acima.
Olá, Frank
Obrigada. O L realmente ajudou.
Queria perguntar outra coisa. A maneira como a query string é construída em php pode fazer com que os RewriteRule do htaccess não funcionem?
Sim, Lívia, a ordem importa. Voltando ao meu exemplo do artigo: O meu .htaccess tem somente a regra:
RewriteCond %{QUERY_STRING} ^marca=([0-9-a-z-]+)&prod=([0-9-a-z-]+)$ [NC]
Se for requisitada uma URL ?prod=macbook&marca=apple, o meu .htaccess não vai aplicar nenhuma regra. Eu teria que adicionar uma linha que especificasse também essa inversão de parâmetros:
RewriteCond %{QUERY_STRING} ^prod=([0-9-a-z-]+)&marca=([0-9-a-z-]+)$ [NC]
Aí sim ele vai saber o que fazer.
Parabéns pela matéria Frank.
Ajudou muito mais me dá uma luz, tenho alguns erros 404 no Google Webmaster Tools e preciso redirecioná-los via .htacces com o 301, mais não funcionou pois o link tem um complemente.
imprimir_ficha_imovel_cliente.php?imprimir=sim&id=mxwidgets.js.php
Detalhe esse link não tem uma página para ser editado, o Google fez essa requisição e não retorna nada, retorna uma página com erro portanto se eu der o redirect não funciona por conta do que está depois do ?.
imprimir_ficha_imovel_cliente.php
Redirect só aqui funcionou mais com todo o link é impossível..
Teria uma solução? Ajuda.?
Obrigado.!
Olá Junior. Se entendi bem o seu problema, este artigo é precisamente a resposta para o que você precisa… Tente usar algo como:
RewriteEngine On
RewriteCond %{QUERY_STRING} !=””
RewriteCond %{QUERY_STRING} ^imprimir=sim&id=mxwidgets.js.php$ [NC]
RewriteRule ^imprimir_ficha_imovel_cliente.php(.*)$ http://www.seusite.com/url-certa? [R=301,L]
Isso vai redirecionar exclusivamente essa URL e com os parâmetros da forma que está escrito ali.
Veja se resolve.
Eu utilizo a regra abaixo para redirecionar toda a navegação para a página index.php e trato a query string enviada para ela contendo o alvo da navegação:
RewriteRule ^(.*)$ index.php?url_amigavel=$1
Recentemente mudei as urls do meu site e fiz alguns redirecionamentos de links antigos para os links atualizados, tentando não perder a indexação das páginas só que caí em um problema.
Quando faço esse redirecionamento, a url exibida para o usuário passa a ser :
Página antiga acessada: http://www.meusite.com.br/pagina
Resultado para o usuário: http://www.meusite.com.br/nova_pagina?url_amigavel=pagina
Onde estou errando?
Díficil dizer onde está o erro, Gustavo…
Você está utilizando o RewriteCond?
Você viu que no RewriteCond, para você “chamar” o valor do parâmetro no redirecionamento, o símbolo correto é o % e não o $?
Você usou a ferramenta de testar .htaccess?
Você pode passar mais detalhes? Eu não entendi muito bem o seu caso…
Abraços,
Grato pelo seu artigo que me ajudou a redirecionar um bug de url e também me ajudou a aprender … Abraços
Gostaria de saber o seguinte tenho um site em wordpress e queria saber se via htaccess pode-se redirecionar um post x para um post y (esse aki tem conteudo)
ai começei assim
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
redirect 301 /magnesiumforlife.com/2012/09/teste
http://magnesiumforlife.com/2012/09/testeredirecinamento/
RewriteCond %{HTTP_HOST} ^magnesiumforlife.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.magnesiumforlife.com$
RewriteRule ^index.shtml$ “http://www.magnesiumforlife.com/index.php” [R=301,L]
———————————————
Esta certo a mina escrita
Obs testei desse jeito e não redireciona :/ :p
atte andré
Andre, temos um outro artigo aqui no site que pode te ajudar: Redirecionamento 301 em várias linguagens de programação.
Olá Frank,
Estou com uma dúvida sobre URLs, qual dessas abaixo seria melhor para o SEO.
nomedosite.com.br/eletronicos/calculadora-xyz
eletronicos.nomedosite.com.br/calculadora-xyz
eletronicos.nomedosite.com.br/calculadoras/calculadora-xyz
No caso eletronicos seria uma categoria e calculadoras uma subcategoria. Você achar que vale a pena por a categoria e a subcategoria na url?
Sim, prefiro manter toda a estrutura em subdiretórios:
– site.com.br/categoria/subcategoria/produto-ou-servico
Ola, minha dúvida é a seguinte. Digamos que eu tenha criado as URLs amigáveis e depois de um tempo alterei a forma de exibi-la, mas em diversos lugares estão com a forma antiga, tratar elas com o Rewrite é simples, porém digamos que tenho muitos links para ser tratado e meu servidor não permite que eu gere o header(Location) no PHP, então estou utilizando o window.location do Javascript. Como faço para que o Google entenda que esse window.location é um redirecionamento 301?
Rodrigo, o Google não resolve todo tipo de javascript, então sua melhor saída seria ir para o .htaccess e providenciar os devidos redirecionamentos 301, pois assim você terá a certeza de que o comportamento está correto para os usuários e para o Google.
Em último caso, se não for possível fazer o redirecionamento 301 propriamente, a alternativa é usar a canonical tag.
Certo, porém se eu usar o window.location porque realmente não há a possibilidade de usar o htaccess (pois preciso verificar com o PHP se o link é válido ou não, por ser um link dinâmico), o que devo exibir antes do window.location…. ?
COLOCO O AQUI?
OU COLOCO O AQUI?
Desde já obrigado pela atenção.
Além de ter um excelente curso, é uma equipe muito atenciosa ao seu público.
haha ele ocultou minhas TAGS HTML…
bom só para tentar resumir, o primeiro “COLOCO AQUI?” fica abaixo o canonical indicando a nova página, e o degundo “COLOCO AQUI?” é o (script) window.location (/script) dentro do body.
A canonical tag sempre vai dentro do cabeçalho (< head>). O window.location você pode usar após a canonical tag, seja no body ou head.
Sem dúvidas esse tutorial é mais do que completo! Vlw Frank
Frank, será que consegue me ajudar? como faço para fazer um redirecionamento de uma url que contém sinal de +(mais) como o exemplo abaixo:
Tentei assim mas não funciona devido aos sinais de +(mais)
redirect 301 /url.errada.htm+url.erra+do+url+da+paraiba.com.br novo.site/url.certa/
Olá Frank, testei seu código e a página gera um loop de redirecionamento, estou tentando fazer com que a página dicas.php?cate=nome-categoria redirecione para /dicas/nome-categoria.html para que o endereço não seja mais acessado pelo dicas.php.
Obrigado pela atenção.
Muito bom o seu post, me ajudou bastante. Obrigado.
meu amigo vc e monstro, esta de parabens!!!!!