NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Yelp Biz – See My Photos Button
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Adds "See my photos" button next to "See all ### photos" on Yelp business pages
// @license MIT; https://spdx.org/licenses/MIT.html
// @copyright 2025, Frostlight (https://openuserjs.org/users/Frostlight)
// @icon https://raw.githubusercontent.com/Frostlight/Userscripts-YelpMyPhotos/master/icon.png
// @homepageURL https://github.com/Frostlight
// @supportURL mailto:frostlight@users.noreply.github.com
// @match https://www.yelp.ca/biz/*
// @match https://www.yelp.com/biz/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Get user ID using working methods
function getCurrentUserId() {
// Method 1: Check window.OneTrust.dataSubjectParams.id
try {
if (window.OneTrust && window.OneTrust.dataSubjectParams && window.OneTrust.dataSubjectParams.id) {
const oneTrustId = window.OneTrust.dataSubjectParams.id;
const match = oneTrustId.match(/^consumer-(.+)$/);
if (match) {
return match[1];
}
}
} catch (e) {
console.error('Yelp My Photos: Failed to extract user ID from window.OneTrust.dataSubjectParams -', e);
}
// Method 2: Parse from script tags
try {
const scripts = document.querySelectorAll('script[type="application/json"], script');
for (const script of scripts) {
const content = script.textContent;
if (content.includes('userId') || content.includes('userid')) {
// Try pattern: "userId" or "userIdEncid"
const userIdMatch = content.match(/"userId(?:Encid)?":\s*"([^"]+)"/);
if (userIdMatch) {
return userIdMatch[1];
}
// Try lowercase pattern
const lowerMatch = content.match(/"userid":\s*"([^"]+)"/i);
if (lowerMatch) {
return lowerMatch[1];
}
}
}
} catch (e) {
console.error('Yelp My Photos: Failed to parse user ID from script tags -', e);
}
console.warn('Yelp My Photos: Could not find user ID. User may not be logged in.');
return null;
}
// Get business alias from URL
function getBusinessAlias() {
const match = window.location.pathname.match(/\/biz\/([^/?]+)/);
if (!match) {
console.error('Yelp My Photos: Could not extract business alias from URL:', window.location.pathname);
}
return match ? match[1] : null;
}
// Create and inject the button
function injectButton() {
// Find the photo-header-buttons container
const container = document.querySelector('div[class*="photo-header-buttons"]');
if (!container) {
return false;
}
// Check if we already injected
if (container.querySelector('[data-my-photos-btn]')) {
return true;
}
const userId = getCurrentUserId();
if (!userId) {
return false;
}
const businessAlias = getBusinessAlias();
if (!businessAlias) {
return false;
}
try {
// Find any existing button span to clone its structure
const existingSpan = container.querySelector('span[class*="y-css-"]');
if (!existingSpan) {
console.error('Yelp My Photos: Could not find button structure to clone');
return false;
}
// Clone the span
const newSpan = existingSpan.cloneNode(true);
// Update the link
const newLink = newSpan.querySelector('a');
newLink.href = `/biz_photos/${businessAlias}?userid=${userId}`;
newLink.setAttribute('data-my-photos-btn', 'true');
// Update the text
const textSpan = newLink.querySelector('span[class*="y-css-"]');
if (textSpan) {
textSpan.textContent = 'See my photos';
}
// Insert at the beginning of the container (to the left)
container.insertBefore(newSpan, container.firstChild);
return true;
} catch (e) {
console.error('Yelp My Photos: Failed to inject "See my photos" button -', e);
return false;
}
}
// Watch for changes and re-inject if needed
function watchForChanges() {
const observer = new MutationObserver(() => {
injectButton();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
// Wait for document to be complete
function init() {
if (document.readyState === 'complete') {
injectButton();
watchForChanges();
} else {
window.addEventListener('load', () => {
injectButton();
watchForChanges();
});
}
}
init();
})();